diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-12-01 11:08:04 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-12-01 11:08:04 +0000 |
commit | 4b08eb6308ca90a6c08e2fc79d100821b1b1f6aa (patch) | |
tree | 867cbbe32a66fd7d62dd9ce9df23a23fefdb8290 /lib/Sema | |
parent | 6df2408694f81a03eb8b0e3b013272042233c061 (diff) | |
download | FreeBSD-src-4b08eb6308ca90a6c08e2fc79d100821b1b1f6aa.zip FreeBSD-src-4b08eb6308ca90a6c08e2fc79d100821b1b1f6aa.tar.gz |
Update clang to r90226.
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/CodeCompleteConsumer.cpp | 492 | ||||
-rw-r--r-- | lib/Sema/Lookup.h | 46 | ||||
-rw-r--r-- | lib/Sema/ParseAST.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 354 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 103 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 183 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 223 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 230 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 1957 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 210 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 45 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 52 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 556 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 246 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 723 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 108 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 54 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 38 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 673 |
21 files changed, 3630 insertions, 2682 deletions
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index a9d8301..91b16d3 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -14,10 +14,10 @@ #include "clang/AST/DeclCXX.h" #include "clang/Parse/Scope.h" #include "clang/Lex/Preprocessor.h" +#include "clang-c/Index.h" #include "Sema.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cstring> @@ -210,306 +210,111 @@ CodeCompletionString *CodeCompletionString::Clone() const { return Result; } -namespace { - // Escape a string for XML-like formatting. - struct EscapedString { - EscapedString(llvm::StringRef Str) : Str(Str) { } - - llvm::StringRef Str; - }; - - llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, EscapedString EStr) { - llvm::StringRef Str = EStr.Str; - while (!Str.empty()) { - // Find the next escaped character. - llvm::StringRef::size_type Pos = Str.find_first_of("<>&\"'"); - - // Print everything before that escaped character. - OS << Str.substr(0, Pos); +static void WriteUnsigned(llvm::raw_ostream &OS, unsigned Value) { + OS.write((const char *)&Value, sizeof(unsigned)); +} - // If we didn't find any escaped characters, we're done. - if (Pos == llvm::StringRef::npos) - break; - - // Print the appropriate escape sequence. - switch (Str[Pos]) { - case '<': OS << "<"; break; - case '>': OS << ">"; break; - case '&': OS << "&"; break; - case '"': OS << """; break; - case '\'': OS << "'"; break; - } - - // Remove everything up to and including that escaped character. - Str = Str.substr(Pos + 1); - } - - return OS; - } - - /// \brief Remove XML-like escaping from a string. - std::string UnescapeString(llvm::StringRef Str) { - using llvm::StringRef; - - std::string Result; - llvm::raw_string_ostream OS(Result); - - while (!Str.empty()) { - StringRef::size_type Amp = Str.find('&'); - OS << Str.substr(0, Amp); - - if (Amp == StringRef::npos) - break; - - StringRef::size_type Semi = Str.substr(Amp).find(';'); - if (Semi == StringRef::npos) { - // Malformed input; do the best we can. - OS << '&'; - Str = Str.substr(Amp + 1); - continue; - } - - char Unescaped = llvm::StringSwitch<char>(Str.substr(Amp + 1, Semi - 1)) - .Case("lt", '<') - .Case("gt", '>') - .Case("amp", '&') - .Case("quot", '"') - .Case("apos", '\'') - .Default('\0'); - - if (Unescaped) - OS << Unescaped; - else - OS << Str.substr(Amp, Semi + 1); - Str = Str.substr(Amp + Semi + 1); - } - - return OS.str(); - } +static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd, + unsigned &Value) { + if (Memory + sizeof(unsigned) > MemoryEnd) + return true; + + memmove(&Value, Memory, sizeof(unsigned)); + Memory += sizeof(unsigned); + return false; } void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const { + // Write the number of chunks. + WriteUnsigned(OS, size()); + for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { + WriteUnsigned(OS, C->Kind); + switch (C->Kind) { case CK_TypedText: - OS << "<typed-text>" << EscapedString(C->Text) << "</>"; - break; case CK_Text: - OS << "<text>" << EscapedString(C->Text) << "</>"; - break; - case CK_Optional: - OS << "<optional>"; - C->Optional->Serialize(OS); - OS << "</>"; - break; case CK_Placeholder: - OS << "<placeholder>" << EscapedString(C->Text) << "</>"; - break; case CK_Informative: - OS << "<informative>" << EscapedString(C->Text) << "</>"; + case CK_CurrentParameter: { + const char *Text = C->Text; + unsigned StrLen = strlen(Text); + WriteUnsigned(OS, StrLen); + OS.write(Text, StrLen); break; - case CK_CurrentParameter: - OS << "<current-parameter>" << EscapedString(C->Text) << "</>"; + } + + case CK_Optional: + C->Optional->Serialize(OS); break; + case CK_LeftParen: - OS << "<lparen/>"; - break; case CK_RightParen: - OS << "<rparen/>"; - break; case CK_LeftBracket: - OS << "<lbracket/>"; - break; case CK_RightBracket: - OS << "<rbracket/>"; - break; case CK_LeftBrace: - OS << "<lbrace/>"; - break; case CK_RightBrace: - OS << "<rbrace/>"; - break; case CK_LeftAngle: - OS << "<langle/>"; - break; case CK_RightAngle: - OS << "<rangle/>"; - break; case CK_Comma: - OS << "<comma/>"; break; - } + } } } -/// \brief Parse the next XML-ish tag of the form <blah>. -/// -/// \param Str the string in which we're looking for the next tag. -/// -/// \param TagPos if successful, will be set to the start of the tag we found. -/// -/// \param Standalone will indicate whether this is a "standalone" tag that -/// has no associated data, e.g., <comma/>. -/// -/// \param Terminator will indicate whether this is a terminating tag (that is -/// or starts with '/'). -/// -/// \returns the tag itself, without the angle brackets. -static llvm::StringRef ParseNextTag(llvm::StringRef Str, - llvm::StringRef::size_type &StartTag, - llvm::StringRef::size_type &AfterTag, - bool &Standalone, bool &Terminator) { - using llvm::StringRef; - - Standalone = false; - Terminator = false; - AfterTag = StringRef::npos; - - // Find the starting '<'. - StartTag = Str.find('<'); - if (StartTag == StringRef::npos) - return llvm::StringRef(); - - // Find the corresponding '>'. - llvm::StringRef::size_type EndTag = Str.substr(StartTag).find('>'); - if (EndTag == StringRef::npos) - return llvm::StringRef(); - AfterTag = StartTag + EndTag + 1; - - // Determine whether this is a terminating tag. - if (Str[StartTag + 1] == '/') { - Terminator = true; - Str = Str.substr(1); - --EndTag; - } - - // Determine whether this is a standalone tag. - if (!Terminator && Str[StartTag + EndTag - 1] == '/') { - Standalone = true; - if (EndTag > 1) - --EndTag; - } - - return Str.substr(StartTag + 1, EndTag - 1); -} +CodeCompletionString *CodeCompletionString::Deserialize(const char *&Str, + const char *StrEnd) { + if (Str == StrEnd || *Str == 0) + return 0; -CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) { - using llvm::StringRef; - CodeCompletionString *Result = new CodeCompletionString; - - do { - // Parse the next tag. - StringRef::size_type StartTag, AfterTag; - bool Standalone, Terminator; - StringRef Tag = ParseNextTag(Str, StartTag, AfterTag, Standalone, - Terminator); - - if (StartTag == StringRef::npos) + unsigned NumBlocks; + if (ReadUnsigned(Str, StrEnd, NumBlocks)) + return Result; + + for (unsigned I = 0; I != NumBlocks; ++I) { + if (Str + 1 >= StrEnd) break; - - // Figure out what kind of chunk we have. - const unsigned UnknownKind = 10000; - unsigned Kind = llvm::StringSwitch<unsigned>(Tag) - .Case("typed-text", CK_TypedText) - .Case("text", CK_Text) - .Case("optional", CK_Optional) - .Case("placeholder", CK_Placeholder) - .Case("informative", CK_Informative) - .Case("current-parameter", CK_CurrentParameter) - .Case("lparen", CK_LeftParen) - .Case("rparen", CK_RightParen) - .Case("lbracket", CK_LeftBracket) - .Case("rbracket", CK_RightBracket) - .Case("lbrace", CK_LeftBrace) - .Case("rbrace", CK_RightBrace) - .Case("langle", CK_LeftAngle) - .Case("rangle", CK_RightAngle) - .Case("comma", CK_Comma) - .Default(UnknownKind); - - // If we've hit a terminator tag, we're done. - if (Terminator) + + // Parse the next kind. + unsigned KindValue; + if (ReadUnsigned(Str, StrEnd, KindValue)) + return Result; + + switch (ChunkKind Kind = (ChunkKind)KindValue) { + case CK_TypedText: + case CK_Text: + case CK_Placeholder: + case CK_Informative: + case CK_CurrentParameter: { + unsigned StrLen; + if (ReadUnsigned(Str, StrEnd, StrLen) || (Str + StrLen > StrEnd)) + return Result; + + Result->AddChunk(Chunk(Kind, StringRef(Str, StrLen))); + Str += StrLen; break; - - // Consume the tag. - Str = Str.substr(AfterTag); - - // Handle standalone tags now, since they don't need to be matched to - // anything. - if (Standalone) { - // Ignore anything we don't know about. - if (Kind == UnknownKind) - continue; - - switch ((ChunkKind)Kind) { - case CK_TypedText: - case CK_Text: - case CK_Optional: - case CK_Placeholder: - case CK_Informative: - case CK_CurrentParameter: - // There is no point in creating empty chunks of these kinds. - break; - - case CK_LeftParen: - case CK_RightParen: - case CK_LeftBracket: - case CK_RightBracket: - case CK_LeftBrace: - case CK_RightBrace: - case CK_LeftAngle: - case CK_RightAngle: - case CK_Comma: - Result->AddChunk(Chunk((ChunkKind)Kind)); - break; - } - - continue; } - - if (Kind == CK_Optional) { - // Deserialize the optional code-completion string. - std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str)); + + case CK_Optional: { + std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str, StrEnd)); Result->AddOptionalChunk(Optional); + break; } - - StringRef EndTag = ParseNextTag(Str, StartTag, AfterTag, Standalone, - Terminator); - if (StartTag == StringRef::npos || !Terminator || Standalone) - break; // Parsing failed; just give up. - - if (EndTag.empty() || Tag == EndTag) { - // Found the matching end tag. Add this chunk based on the text - // between the tags, then consume that input. - StringRef Text = Str.substr(0, StartTag); - switch ((ChunkKind)Kind) { - case CK_TypedText: - case CK_Text: - case CK_Placeholder: - case CK_Informative: - case CK_CurrentParameter: - case CK_LeftParen: - case CK_RightParen: - case CK_LeftBracket: - case CK_RightBracket: - case CK_LeftBrace: - case CK_RightBrace: - case CK_LeftAngle: - case CK_RightAngle: - case CK_Comma: - Result->AddChunk(Chunk((ChunkKind)Kind, UnescapeString(Text))); - break; - - case CK_Optional: - // We've already added the optional chunk. - break; - } + + case CK_LeftParen: + case CK_RightParen: + case CK_LeftBracket: + case CK_RightBracket: + case CK_LeftBrace: + case CK_RightBrace: + case CK_LeftAngle: + case CK_RightAngle: + case CK_Comma: + Result->AddChunk(Chunk(Kind)); + break; } - - // Remove this tag. - Str = Str.substr(AfterTag); - } while (!Str.empty()); + }; return Result; } @@ -633,62 +438,110 @@ CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, unsigned NumResults) { // Print the results. for (unsigned I = 0; I != NumResults; ++I) { - OS << "COMPLETION:" << Results[I].Rank << ":"; + CXCursorKind Kind = CXCursor_NotImplemented; + switch (Results[I].Kind) { - case Result::RK_Declaration: - if (RecordDecl *Record = dyn_cast<RecordDecl>(Results[I].Declaration)) { - if (Record->isStruct()) - OS << "Struct:"; - else if (Record->isUnion()) - OS << "Union:"; - else - OS << "Class:"; - } else if (ObjCMethodDecl *Method - = dyn_cast<ObjCMethodDecl>(Results[I].Declaration)) { - if (Method->isInstanceMethod()) - OS << "ObjCInstanceMethod:"; - else - OS << "ObjCClassMethod:"; - } else { - OS << Results[I].Declaration->getDeclKindName() << ":"; - } - if (CodeCompletionString *CCS - = Results[I].CreateCodeCompletionString(SemaRef)) { - CCS->Serialize(OS); - delete CCS; - } else { - OS << "<typed-text>" - << Results[I].Declaration->getNameAsString() - << "</>"; - } + case Result::RK_Declaration: + switch (Results[I].Declaration->getKind()) { + case Decl::Record: + case Decl::CXXRecord: + case Decl::ClassTemplateSpecialization: { + RecordDecl *Record = cast<RecordDecl>(Results[I].Declaration); + if (Record->isStruct()) + Kind = CXCursor_StructDecl; + else if (Record->isUnion()) + Kind = CXCursor_UnionDecl; + else + Kind = CXCursor_ClassDecl; + break; + } + + case Decl::ObjCMethod: { + ObjCMethodDecl *Method = cast<ObjCMethodDecl>(Results[I].Declaration); + if (Method->isInstanceMethod()) + Kind = CXCursor_ObjCInstanceMethodDecl; + else + Kind = CXCursor_ObjCClassMethodDecl; + break; + } - OS << '\n'; + case Decl::Typedef: + Kind = CXCursor_TypedefDecl; break; - case Result::RK_Keyword: - OS << "Keyword:<typed-text>" << Results[I].Keyword << "</>\n"; + case Decl::Enum: + Kind = CXCursor_EnumDecl; break; - case Result::RK_Macro: { - OS << "Macro:"; - if (CodeCompletionString *CCS - = Results[I].CreateCodeCompletionString(SemaRef)) { - CCS->Serialize(OS); - delete CCS; - } else { - OS << "<typed-text>" << Results[I].Macro->getName() << "</>"; - } - OS << '\n'; + case Decl::Field: + Kind = CXCursor_FieldDecl; + break; + + case Decl::EnumConstant: + Kind = CXCursor_EnumConstantDecl; + break; + + case Decl::Function: + case Decl::CXXMethod: + case Decl::CXXConstructor: + case Decl::CXXDestructor: + case Decl::CXXConversion: + Kind = CXCursor_FunctionDecl; + break; + + case Decl::Var: + Kind = CXCursor_VarDecl; + break; + + case Decl::ParmVar: + Kind = CXCursor_ParmDecl; + break; + + case Decl::ObjCInterface: + Kind = CXCursor_ObjCInterfaceDecl; + break; + + case Decl::ObjCCategory: + Kind = CXCursor_ObjCCategoryDecl; + break; + + case Decl::ObjCProtocol: + Kind = CXCursor_ObjCProtocolDecl; break; - } - case Result::RK_Pattern: { - OS << "Pattern:"; - Results[I].Pattern->Serialize(OS); - OS << '\n'; + case Decl::ObjCProperty: + Kind = CXCursor_ObjCPropertyDecl; + break; + + case Decl::ObjCIvar: + Kind = CXCursor_ObjCIvarDecl; + break; + + case Decl::ObjCImplementation: + Kind = CXCursor_ObjCClassDefn; + break; + + case Decl::ObjCCategoryImpl: + Kind = CXCursor_ObjCCategoryDefn; + break; + + default: break; } + break; + + case Result::RK_Keyword: + case Result::RK_Macro: + case Result::RK_Pattern: + Kind = CXCursor_NotImplemented; + break; } + + WriteUnsigned(OS, Kind); + CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef); + assert(CCS && "No code-completion string?"); + CCS->Serialize(OS); + delete CCS; } // Once we've printed the code-completion results, suppress remaining @@ -703,13 +556,12 @@ CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, OverloadCandidate *Candidates, unsigned NumCandidates) { for (unsigned I = 0; I != NumCandidates; ++I) { - if (CodeCompletionString *CCS - = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) { - OS << "OVERLOAD:"; - CCS->Serialize(OS); - OS << '\n'; - delete CCS; - } + WriteUnsigned(OS, CXCursor_NotImplemented); + CodeCompletionString *CCS + = Candidates[I].CreateSignatureString(CurrentArg, SemaRef); + assert(CCS && "No code-completion string?"); + CCS->Serialize(OS); + delete CCS; } // Once we've printed the code-completion results, suppress remaining diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h index 10cc818..e2134a2 100644 --- a/lib/Sema/Lookup.h +++ b/lib/Sema/Lookup.h @@ -208,6 +208,15 @@ public: return getResultKind() == Found; } + /// Determines if the results are overloaded. + bool isOverloadedResult() const { + return getResultKind() == FoundOverloaded; + } + + bool isUnresolvableResult() const { + return getResultKind() == FoundUnresolvedValue; + } + LookupResultKind getResultKind() const { sanity(); return ResultKind; @@ -280,6 +289,12 @@ public: /// ambiguous and overloaded lookups. NamedDecl *getAsSingleDecl(ASTContext &Context) const; + template <class DeclClass> + DeclClass *getAsSingle() const { + if (getResultKind() != Found) return 0; + return dyn_cast<DeclClass>(getFoundDecl()); + } + /// \brief Fetch the unique decl found by this lookup. Asserts /// that one was found. /// @@ -368,14 +383,14 @@ public: class Filter { LookupResult &Results; unsigned I; - bool ErasedAny; + bool Changed; #ifndef NDEBUG bool CalledDone; #endif friend class LookupResult; Filter(LookupResult &Results) - : Results(Results), I(0), ErasedAny(false) + : Results(Results), I(0), Changed(false) #ifndef NDEBUG , CalledDone(false) #endif @@ -402,7 +417,12 @@ public: void erase() { Results.Decls[--I] = Results.Decls.back(); Results.Decls.pop_back(); - ErasedAny = true; + Changed = true; + } + + void replace(NamedDecl *D) { + Results.Decls[I-1] = D; + Changed = true; } void done() { @@ -411,7 +431,7 @@ public: CalledDone = true; #endif - if (ErasedAny) + if (Changed) Results.resolveKindAfterFilter(); } }; @@ -438,15 +458,25 @@ private: void sanity() const { assert(ResultKind != NotFound || Decls.size() == 0); assert(ResultKind != Found || Decls.size() == 1); - assert(ResultKind == NotFound || ResultKind == Found || - ResultKind == FoundUnresolvedValue || - (ResultKind == Ambiguous && Ambiguity == AmbiguousBaseSubobjects) - || Decls.size() > 1); + assert(ResultKind != FoundOverloaded || Decls.size() > 1 || + (Decls.size() == 1 && + isa<FunctionTemplateDecl>(Decls[0]->getUnderlyingDecl()))); + assert(ResultKind != FoundUnresolvedValue || sanityCheckUnresolved()); + assert(ResultKind != Ambiguous || Decls.size() > 1 || + (Decls.size() == 1 && Ambiguity == AmbiguousBaseSubobjects)); assert((Paths != NULL) == (ResultKind == Ambiguous && (Ambiguity == AmbiguousBaseSubobjectTypes || Ambiguity == AmbiguousBaseSubobjects))); } + bool sanityCheckUnresolved() const { + for (DeclsTy::const_iterator I = Decls.begin(), E = Decls.end(); + I != E; ++I) + if (isa<UnresolvedUsingValueDecl>(*I)) + return true; + return false; + } + static void deletePaths(CXXBasePaths *); // Results. diff --git a/lib/Sema/ParseAST.cpp b/lib/Sema/ParseAST.cpp index 7b223a8..7c7df4b 100644 --- a/lib/Sema/ParseAST.cpp +++ b/lib/Sema/ParseAST.cpp @@ -90,8 +90,5 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, Decl::PrintStats(); Stmt::PrintStats(); Consumer->PrintStats(); - - Decl::CollectingStats(false); - Stmt::CollectingStats(false); } } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index fe2d744..f0812bf 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -299,17 +299,15 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { // Built-in ObjC types may already be set by PCHReader (hence isNull checks). if (Context.getObjCSelType().isNull()) { - // Synthesize "typedef struct objc_selector *SEL;" - RecordDecl *SelTag = CreateStructDecl(Context, "objc_selector"); - PushOnScopeChains(SelTag, TUScope); - - QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag)); + // Create the built-in typedef for 'SEL'. + QualType SelT = Context.getPointerType(Context.ObjCBuiltinSelTy); DeclaratorInfo *SelInfo = Context.getTrivialDeclaratorInfo(SelT); TypedefDecl *SelTypedef = TypedefDecl::Create(Context, CurContext, SourceLocation(), &Context.Idents.get("SEL"), SelInfo); PushOnScopeChains(SelTypedef, TUScope); Context.setObjCSelType(Context.getTypeDeclType(SelTypedef)); + Context.ObjCSelRedefinitionType = Context.getObjCSelType(); } // Synthesize "@class Protocol; @@ -354,7 +352,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), PreDeclaratorDC(0), CurBlock(0), PackContext(0), ParsingDeclDepth(0), IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0), - GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated), + GlobalNewDeleteDeclared(false), CompleteTranslationUnit(CompleteTranslationUnit), NumSFINAEErrors(0), NonInstantiationEntries(0), CurrentInstantiationScope(0) @@ -365,6 +363,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, // Tell diagnostics how to render things from the AST library. PP.getDiagnostics().SetArgToStringFn(ConvertArgToStringFn, &Context); + + ExprEvalContexts.push_back( + ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0)); } /// Retrieves the width and signedness of the given integer type, @@ -594,7 +595,7 @@ static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, unsigned diag) { /// Implements -Wconversion. static void CheckImplicitConversion(Sema &S, Expr *E, QualType T) { // Don't diagnose in unevaluated contexts. - if (S.ExprEvalContext == Sema::Unevaluated) + if (S.ExprEvalContexts.back().Context == Sema::Unevaluated) return; // Don't diagnose for value-dependent expressions. diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index ad4c90b..b594ece 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -330,18 +330,49 @@ public: /// have been declared. bool GlobalNewDeleteDeclared; - /// The current expression evaluation context. - ExpressionEvaluationContext ExprEvalContext; - - typedef std::vector<std::pair<SourceLocation, Decl *> > + /// \brief The set of declarations that have been referenced within + /// a potentially evaluated expression. + typedef std::vector<std::pair<SourceLocation, Decl *> > PotentiallyReferencedDecls; - /// A stack of declarations, each element of which is a set of declarations - /// that will be marked as referenced if the corresponding potentially - /// potentially evaluated expression is potentially evaluated. Each element - /// in the stack corresponds to a PotentiallyPotentiallyEvaluated expression - /// evaluation context. - std::list<PotentiallyReferencedDecls> PotentiallyReferencedDeclStack; + /// \brief Data structure used to record current or nested + /// expression evaluation contexts. + struct ExpressionEvaluationContextRecord { + /// \brief The expression evaluation context. + ExpressionEvaluationContext Context; + + /// \brief The number of temporaries that were active when we + /// entered this expression evaluation context. + unsigned NumTemporaries; + + /// \brief The set of declarations referenced within a + /// potentially potentially-evaluated context. + /// + /// When leaving a potentially potentially-evaluated context, each + /// of these elements will be as referenced if the corresponding + /// potentially potentially evaluated expression is potentially + /// evaluated. + PotentiallyReferencedDecls *PotentiallyReferenced; + + ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, + unsigned NumTemporaries) + : Context(Context), NumTemporaries(NumTemporaries), + PotentiallyReferenced(0) { } + + void addReferencedDecl(SourceLocation Loc, Decl *Decl) { + if (!PotentiallyReferenced) + PotentiallyReferenced = new PotentiallyReferencedDecls; + PotentiallyReferenced->push_back(std::make_pair(Loc, Decl)); + } + + void Destroy() { + delete PotentiallyReferenced; + PotentiallyReferenced = 0; + } + }; + + /// A stack of expression evaluation contexts. + llvm::SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts; /// \brief Whether the code handled by Sema should be considered a /// complete translation unit or not. @@ -428,13 +459,20 @@ public: virtual void DeleteExpr(ExprTy *E); virtual void DeleteStmt(StmtTy *S); - OwningExprResult Owned(Expr* E) { return OwningExprResult(*this, E); } + OwningExprResult Owned(Expr* E) { + assert(!E || E->isRetained()); + return OwningExprResult(*this, E); + } OwningExprResult Owned(ExprResult R) { if (R.isInvalid()) return ExprError(); + assert(!R.get() || ((Expr*) R.get())->isRetained()); return OwningExprResult(*this, R.get()); } - OwningStmtResult Owned(Stmt* S) { return OwningStmtResult(*this, S); } + OwningStmtResult Owned(Stmt* S) { + assert(!S || S->isRetained()); + return OwningStmtResult(*this, S); + } virtual void ActOnEndOfTranslationUnit(); @@ -485,7 +523,7 @@ public: /// \brief Create a LocInfoType to hold the given QualType and DeclaratorInfo. QualType CreateLocInfoType(QualType T, DeclaratorInfo *DInfo); DeclarationName GetNameForDeclarator(Declarator &D); - DeclarationName GetNameFromUnqualifiedId(UnqualifiedId &Name); + DeclarationName GetNameFromUnqualifiedId(const UnqualifiedId &Name); static QualType GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo = 0); bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range); bool CheckDistantExceptionSpec(QualType T); @@ -533,7 +571,8 @@ public: virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, Scope *S, const CXXScopeSpec *SS, - bool isClassName = false); + bool isClassName = false, + TypeTy *ObjectType = 0); virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S); virtual bool DiagnoseUnknownTypeName(const IdentifierInfo &II, SourceLocation IILoc, @@ -893,17 +932,13 @@ public: bool SuppressUserConversions = false, bool ForceRValue = false); void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo *ExplicitTemplateArgs, Expr *Object, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, bool ForceRValue = false); void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, @@ -939,9 +974,7 @@ public: OverloadCandidateSet& CandidateSet); void AddArgumentDependentLookupCandidates(DeclarationName Name, Expr **Args, unsigned NumArgs, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, bool PartialOverloading = false); bool isBetterOverloadCandidate(const OverloadCandidate& Cand1, @@ -958,26 +991,23 @@ public: bool Complain); Expr *FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn); - void AddOverloadedCallCandidates(NamedDecl *Callee, + void AddOverloadedCallCandidates(llvm::SmallVectorImpl<NamedDecl*>& Callees, DeclarationName &UnqualifiedName, - bool &ArgumentDependentLookup, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + bool ArgumentDependentLookup, + const TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, bool PartialOverloading = false); - FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, + FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, + llvm::SmallVectorImpl<NamedDecl*> &Fns, DeclarationName UnqualifiedName, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo *ExplicitTemplateArgs, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation *CommaLocs, SourceLocation RParenLoc, - bool &ArgumentDependentLookup); + bool ArgumentDependentLookup); OwningExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned Opc, @@ -1260,6 +1290,7 @@ public: virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc); + virtual void ActOnForEachDeclStmt(DeclGroupPtrTy Decl); virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprArg LHSVal, SourceLocation DotDotDotLoc, ExprArg RHSVal, SourceLocation ColonLoc); @@ -1273,13 +1304,16 @@ public: SourceLocation ColonLoc, StmtArg SubStmt); virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc, - FullExprArg CondVal, StmtArg ThenVal, + FullExprArg CondVal, DeclPtrTy CondVar, + StmtArg ThenVal, SourceLocation ElseLoc, StmtArg ElseVal); - virtual OwningStmtResult ActOnStartOfSwitchStmt(ExprArg Cond); + virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond, + DeclPtrTy CondVar); virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, StmtArg Body); virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc, - FullExprArg Cond, StmtArg Body); + FullExprArg Cond, + DeclPtrTy CondVar, StmtArg Body); virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body, SourceLocation WhileLoc, SourceLocation CondLParen, ExprArg Cond, @@ -1287,8 +1321,10 @@ public: virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - StmtArg First, ExprArg Second, - ExprArg Third, SourceLocation RParenLoc, + StmtArg First, FullExprArg Second, + DeclPtrTy SecondVar, + FullExprArg Third, + SourceLocation RParenLoc, StmtArg Body); virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, SourceLocation LParenLoc, @@ -1379,12 +1415,10 @@ public: const PartialDiagnostic &PD, bool Equality = false); - virtual ExpressionEvaluationContext + virtual void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext); - virtual void - PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext, - ExpressionEvaluationContext NewContext); + virtual void PopExpressionEvaluationContext(); void MarkDeclarationReferenced(SourceLocation Loc, Decl *D); @@ -1396,10 +1430,19 @@ public: UnqualifiedId &Name, bool HasTrailingLParen, bool IsAddressOfOperand); + + OwningExprResult LookupInObjCMethod(LookupResult &R, + Scope *S, + IdentifierInfo *II); + + OwningExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + bool CheckForImplicitMember, + const TemplateArgumentListInfo *TemplateArgs); OwningExprResult BuildDeclRefExpr(NamedDecl *D, QualType Ty, - SourceLocation Loc, bool TypeDependent, - bool ValueDependent, + SourceLocation Loc, const CXXScopeSpec *SS = 0); VarDecl *BuildAnonymousStructUnionMemberPath(FieldDecl *Field, llvm::SmallVectorImpl<FieldDecl *> &Path); @@ -1408,15 +1451,27 @@ public: FieldDecl *Field, Expr *BaseObjectExpr = 0, SourceLocation OpLoc = SourceLocation()); - OwningExprResult ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, - DeclarationName Name, - bool HasTrailingLParen, - const CXXScopeSpec *SS, - bool isAddressOfOperand = false); - OwningExprResult BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, - bool HasTrailingLParen, - const CXXScopeSpec *SS, - bool isAddressOfOperand); + OwningExprResult BuildImplicitMemberReferenceExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs); + bool UseArgumentDependentLookup(const CXXScopeSpec &SS, + const LookupResult &R, + bool HasTrailingLParen); + + OwningExprResult BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc); + OwningExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs); + + OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool ADL); + OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, + SourceLocation Loc, + NamedDecl *D); virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind); @@ -1424,9 +1479,10 @@ public: virtual OwningExprResult ActOnCharacterConstant(const Token &); virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, ExprArg Val); - virtual OwningExprResult ActOnParenListExpr(SourceLocation L, + virtual OwningExprResult ActOnParenOrParenListExpr(SourceLocation L, SourceLocation R, - MultiExprArg Val); + MultiExprArg Val, + TypeTy *TypeOfCast=0); /// ActOnStringLiteral - The specified tokens were lexed as pasted string /// fragments (e.g. "foo" "bar" L"baz"). @@ -1468,36 +1524,40 @@ public: ExprArg Idx, SourceLocation RLoc); - OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base, + OwningExprResult BuildMemberReferenceExpr(ExprArg Base, SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation MemberLoc, - DeclarationName MemberName, - DeclPtrTy ImplDecl, - const CXXScopeSpec *SS = 0, - NamedDecl *FirstQualifierInScope = 0) { - // FIXME: Temporary helper while we migrate existing calls to - // BuildMemberReferenceExpr to support explicitly-specified template - // arguments. - return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, MemberLoc, - MemberName, false, SourceLocation(), 0, 0, - SourceLocation(), ImplDecl, SS, - FirstQualifierInScope); - } + bool IsArrow, + const CXXScopeSpec &SS, + NamedDecl *FirstQualifierInScope, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs); - OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base, + OwningExprResult BuildMemberReferenceExpr(ExprArg Base, + SourceLocation OpLoc, bool IsArrow, + const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs); + + OwningExprResult LookupMemberExpr(LookupResult &R, Expr *&Base, + bool IsArrow, SourceLocation OpLoc, + const CXXScopeSpec &SS, + NamedDecl *FirstQualifierInScope, + DeclPtrTy ObjCImpDecl); + + bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + const LookupResult &R); + + OwningExprResult ActOnDependentMemberExpr(ExprArg Base, + bool IsArrow, SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation MemberLoc, - DeclarationName MemberName, - bool HasExplicitTemplateArgs, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, - SourceLocation RAngleLoc, - DeclPtrTy ImplDecl, - const CXXScopeSpec *SS, - NamedDecl *FirstQualifierInScope = 0); + const CXXScopeSpec &SS, + NamedDecl *FirstQualifierInScope, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs); virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, @@ -1515,14 +1575,14 @@ public: SourceLocation RParenLoc); void DeconstructCallFunction(Expr *FnExpr, - NamedDecl *&Function, + llvm::SmallVectorImpl<NamedDecl*>& Fns, DeclarationName &Name, NestedNameSpecifier *&Qualifier, SourceRange &QualifierRange, bool &ArgumentDependentLookup, - bool &HasExplicitTemplateArguments, - const TemplateArgumentLoc *&ExplicitTemplateArgs, - unsigned &NumExplicitTemplateArgs); + bool &Overloaded, + bool &HasExplicitTemplateArgs, + TemplateArgumentListInfo &ExplicitTemplateArgs); /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma @@ -1536,6 +1596,9 @@ public: virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, TypeTy *Ty, SourceLocation RParenLoc, ExprArg Op); + virtual bool TypeIsVectorType(TypeTy *Ty) { + return GetTypeFromParser(Ty)->isVectorType(); + } OwningExprResult MaybeConvertParenListExprToParenExpr(Scope *S, ExprArg ME); OwningExprResult ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, @@ -1868,15 +1931,10 @@ public: bool UseGlobal, bool ArrayForm, ExprArg Operand); - /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a - /// C++ if/switch/while/for statement. - /// e.g: "if (int x = f()) {...}" - virtual OwningExprResult ActOnCXXConditionDeclarationExpr(Scope *S, - SourceLocation StartLoc, - Declarator &D, - SourceLocation EqualLoc, - ExprArg AssignExprVal); - + virtual DeclResult ActOnCXXConditionDeclaration(Scope *S, + Declarator &D); + OwningExprResult CheckConditionVariable(VarDecl *ConditionVar); + /// ActOnUnaryTypeTrait - Parsed one of the unary type trait support /// pseudo-functions. virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT, @@ -2028,7 +2086,7 @@ public: Declarator &D, MultiTemplateParamsArg TemplateParameterLists, ExprTy *BitfieldWidth, - ExprTy *Init, + ExprTy *Init, bool IsDefinition, bool Deleted = false); virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorD, @@ -2093,14 +2151,12 @@ public: void CheckConstructor(CXXConstructorDecl *Constructor); QualType CheckDestructorDeclarator(Declarator &D, FunctionDecl::StorageClass& SC); - void CheckDestructor(CXXDestructorDecl *Destructor); + bool CheckDestructor(CXXDestructorDecl *Destructor); void CheckConversionDeclarator(Declarator &D, QualType &R, FunctionDecl::StorageClass& SC); DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion); - bool isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D, - SourceLocation NameLoc, QualType &ThisType, - QualType &MemberType); + bool isImplicitMemberReference(const LookupResult &R, QualType &ThisType); //===--------------------------------------------------------------------===// // C++ Derived Classes @@ -2147,6 +2203,11 @@ public: bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, const CXXMethodDecl *Old); + /// CheckOverridingFunctionAttributes - Checks whether attributes are + /// incompatible or prevent overriding. + bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New, + const CXXMethodDecl *Old); + //===--------------------------------------------------------------------===// // C++ Access Control // @@ -2190,6 +2251,9 @@ public: //===--------------------------------------------------------------------===// // C++ Templates [C++ 14] // + void LookupTemplateName(LookupResult &R, Scope *S, const CXXScopeSpec &SS, + QualType ObjectType, bool EnteringContext); + virtual TemplateNameKind isTemplateName(Scope *S, const CXXScopeSpec &SS, UnqualifiedId &Name, @@ -2235,8 +2299,19 @@ public: SourceLocation LAngleLoc, DeclPtrTy *Params, unsigned NumParams, SourceLocation RAngleLoc); + + /// \brief The context in which we are checking a template parameter + /// list. + enum TemplateParamListContext { + TPC_ClassTemplate, + TPC_FunctionTemplate, + TPC_ClassTemplateMember, + TPC_FriendFunctionTemplate + }; + bool CheckTemplateParameterList(TemplateParameterList *NewParams, - TemplateParameterList *OldParams); + TemplateParameterList *OldParams, + TemplateParamListContext TPC); TemplateParameterList * MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, const CXXScopeSpec &SS, @@ -2251,15 +2326,12 @@ public: TemplateParameterList *TemplateParams, AccessSpecifier AS); - void translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, - llvm::SmallVectorImpl<TemplateArgumentLoc> &TempArgs); + void translateTemplateArguments(const ASTTemplateArgsPtr &In, + TemplateArgumentListInfo &Out); QualType CheckTemplateIdType(TemplateName Template, SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc); + const TemplateArgumentListInfo &TemplateArgs); virtual TypeResult ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc, @@ -2272,26 +2344,20 @@ public: DeclSpec::TST TagSpec, SourceLocation TagLoc); - OwningExprResult BuildTemplateIdExpr(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TemplateName Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc); - - OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS, - TemplateTy Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc); + OwningExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL, + const TemplateArgumentListInfo &TemplateArgs); + OwningExprResult BuildQualifiedTemplateIdExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo &TemplateArgs); virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, const CXXScopeSpec &SS, UnqualifiedId &Name, - TypeTy *ObjectType); + TypeTy *ObjectType, + bool EnteringContext); bool CheckClassTemplatePartialSpecializationArgs( TemplateParameterList *TemplateParams, @@ -2327,11 +2393,7 @@ public: bool &SuppressNew); bool CheckFunctionTemplateSpecialization(FunctionDecl *FD, - bool HasExplicitTemplateArgs, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, - SourceLocation RAngleLoc, + const TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous); bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous); @@ -2365,6 +2427,13 @@ public: SourceLocation TemplateLoc, Declarator &D); + TemplateArgumentLoc + SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + Decl *Param, + TemplateArgumentListBuilder &Converted); + bool CheckTemplateArgument(NamedDecl *Param, const TemplateArgumentLoc &Arg, TemplateDecl *Template, @@ -2374,10 +2443,7 @@ public: bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc, + const TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, TemplateArgumentListBuilder &Converted); @@ -2603,8 +2669,7 @@ public: TemplateDeductionResult SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo &ExplicitTemplateArgs, llvm::SmallVectorImpl<TemplateArgument> &Deduced, llvm::SmallVectorImpl<QualType> &ParamTypes, QualType *FunctionType, @@ -2618,18 +2683,14 @@ public: TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, FunctionDecl *&Specialization, TemplateDeductionInfo &Info); TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType, FunctionDecl *&Specialization, TemplateDeductionInfo &Info); @@ -3312,9 +3373,20 @@ public: VariadicFunction, VariadicBlock, VariadicMethod, - VariadicConstructor + VariadicConstructor, + VariadicDoesNotApply }; + /// GatherArgumentsForCall - Collector argument expressions for various + /// form of call prototypes. + bool GatherArgumentsForCall(SourceLocation CallLoc, + FunctionDecl *FDecl, + const FunctionProtoType *Proto, + unsigned FirstProtoArg, + Expr **Args, unsigned NumArgs, + llvm::SmallVector<Expr *, 8> &AllArgs, + VariadicCallType CallType = VariadicDoesNotApply); + // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but // will warn if the resulting type is not a POD type. bool DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 6dbb442..b386adb 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -206,17 +206,6 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { MaybeAddResult(Result(Using->getTargetDecl(), R.Rank, R.Qualifier), CurContext); - // Handle each declaration in an overload set separately. - if (OverloadedFunctionDecl *Ovl - = dyn_cast<OverloadedFunctionDecl>(R.Declaration)) { - for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(), - FEnd = Ovl->function_end(); - F != FEnd; ++F) - MaybeAddResult(Result(*F, R.Rank, R.Qualifier), CurContext); - - return; - } - Decl *CanonDecl = R.Declaration->getCanonicalDecl(); unsigned IDNS = CanonDecl->getIdentifierNamespace(); @@ -704,7 +693,7 @@ static void AddFunctionParameterChunks(ASTContext &Context, Context.PrintingPolicy); // Add the placeholder string. - CCStr->AddPlaceholderChunk(PlaceholderStr.c_str()); + CCStr->AddPlaceholderChunk(PlaceholderStr); } if (const FunctionProtoType *Proto @@ -778,7 +767,7 @@ static void AddTemplateParameterChunks(ASTContext &Context, CCStr->AddChunk(Chunk(CodeCompletionString::CK_Comma)); // Add the placeholder string. - CCStr->AddPlaceholderChunk(PlaceholderStr.c_str()); + CCStr->AddPlaceholderChunk(PlaceholderStr); } } @@ -797,9 +786,9 @@ void AddQualifierToCompletionString(CodeCompletionString *Result, Qualifier->print(OS, Context.PrintingPolicy); } if (QualifierIsInformative) - Result->AddInformativeChunk(PrintedNNS.c_str()); + Result->AddInformativeChunk(PrintedNNS); else - Result->AddTextChunk(PrintedNNS.c_str()); + Result->AddTextChunk(PrintedNNS); } /// \brief If possible, create a new code completion string for the given @@ -812,17 +801,26 @@ CodeCompletionString * CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { typedef CodeCompletionString::Chunk Chunk; - if (Kind == RK_Keyword) - return 0; + if (Kind == RK_Pattern) + return Pattern->Clone(); + + CodeCompletionString *Result = new CodeCompletionString; + + if (Kind == RK_Keyword) { + Result->AddTypedTextChunk(Keyword); + return Result; + } if (Kind == RK_Macro) { MacroInfo *MI = S.PP.getMacroInfo(Macro); - if (!MI || !MI->isFunctionLike()) - return 0; + assert(MI && "Not a macro?"); + + Result->AddTypedTextChunk(Macro->getName()); + + if (!MI->isFunctionLike()) + return Result; // Format a function-like macro with placeholders for the arguments. - CodeCompletionString *Result = new CodeCompletionString; - Result->AddTypedTextChunk(Macro->getName().str().c_str()); Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end(); A != AEnd; ++A) { @@ -831,7 +829,7 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { if (!MI->isVariadic() || A != AEnd - 1) { // Non-variadic argument. - Result->AddPlaceholderChunk((*A)->getName().str().c_str()); + Result->AddPlaceholderChunk((*A)->getName()); continue; } @@ -843,7 +841,7 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { else { std::string Arg = (*A)->getName(); Arg += "..."; - Result->AddPlaceholderChunk(Arg.c_str()); + Result->AddPlaceholderChunk(Arg); } } Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen)); @@ -854,17 +852,15 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { NamedDecl *ND = Declaration; if (StartsNestedNameSpecifier) { - CodeCompletionString *Result = new CodeCompletionString; - Result->AddTypedTextChunk(ND->getNameAsString().c_str()); + Result->AddTypedTextChunk(ND->getNameAsString()); Result->AddTextChunk("::"); return Result; } if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { - CodeCompletionString *Result = new CodeCompletionString; AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, S.Context); - Result->AddTypedTextChunk(Function->getNameAsString().c_str()); + Result->AddTypedTextChunk(Function->getNameAsString()); Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); AddFunctionParameterChunks(S.Context, Function, Result); Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen)); @@ -872,11 +868,10 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { } if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) { - CodeCompletionString *Result = new CodeCompletionString; AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, S.Context); FunctionDecl *Function = FunTmpl->getTemplatedDecl(); - Result->AddTypedTextChunk(Function->getNameAsString().c_str()); + Result->AddTypedTextChunk(Function->getNameAsString()); // Figure out which template parameters are deduced (or have default // arguments). @@ -926,10 +921,9 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { } if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) { - CodeCompletionString *Result = new CodeCompletionString; AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, S.Context); - Result->AddTypedTextChunk(Template->getNameAsString().c_str()); + Result->AddTypedTextChunk(Template->getNameAsString()); Result->AddChunk(Chunk(CodeCompletionString::CK_LeftAngle)); AddTemplateParameterChunks(S.Context, Template, Result); Result->AddChunk(Chunk(CodeCompletionString::CK_RightAngle)); @@ -937,7 +931,6 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { } if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) { - CodeCompletionString *Result = new CodeCompletionString; Selector Sel = Method->getSelector(); if (Sel.isUnarySelector()) { Result->AddTypedTextChunk(Sel.getIdentifierInfoForSlot(0)->getName()); @@ -993,15 +986,12 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { return Result; } - if (Qualifier) { - CodeCompletionString *Result = new CodeCompletionString; + if (Qualifier) AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, S.Context); - Result->AddTypedTextChunk(ND->getNameAsString().c_str()); - return Result; - } - - return 0; + + Result->AddTypedTextChunk(ND->getNameAsString()); + return Result; } CodeCompletionString * @@ -1019,7 +1009,7 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( // highlighted ellipsis. const FunctionType *FT = getFunctionType(); Result->AddTextChunk( - FT->getResultType().getAsString(S.Context.PrintingPolicy).c_str()); + FT->getResultType().getAsString(S.Context.PrintingPolicy)); Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "...")); Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen)); @@ -1027,10 +1017,10 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( } if (FDecl) - Result->AddTextChunk(FDecl->getNameAsString().c_str()); + Result->AddTextChunk(FDecl->getNameAsString()); else Result->AddTextChunk( - Proto->getResultType().getAsString(S.Context.PrintingPolicy).c_str()); + Proto->getResultType().getAsString(S.Context.PrintingPolicy)); Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs(); @@ -1052,9 +1042,9 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( if (I == CurrentArg) Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, - ArgString.c_str())); + ArgString)); else - Result->AddTextChunk(ArgString.c_str()); + Result->AddTextChunk(ArgString); } if (Proto && Proto->isVariadic()) { @@ -1467,19 +1457,18 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, Expr::hasAnyTypeDependentArguments(Args, NumArgs)) return; - NamedDecl *Function; + llvm::SmallVector<NamedDecl*,8> Fns; DeclarationName UnqualifiedName; NestedNameSpecifier *Qualifier; SourceRange QualifierRange; bool ArgumentDependentLookup; + bool Overloaded; bool HasExplicitTemplateArgs; - const TemplateArgumentLoc *ExplicitTemplateArgs; - unsigned NumExplicitTemplateArgs; + TemplateArgumentListInfo ExplicitTemplateArgs; - DeconstructCallFunction(Fn, - Function, UnqualifiedName, Qualifier, QualifierRange, - ArgumentDependentLookup, HasExplicitTemplateArgs, - ExplicitTemplateArgs, NumExplicitTemplateArgs); + DeconstructCallFunction(Fn, Fns, UnqualifiedName, Qualifier, QualifierRange, + ArgumentDependentLookup, Overloaded, + HasExplicitTemplateArgs, ExplicitTemplateArgs); // FIXME: What if we're calling something that isn't a function declaration? @@ -1488,9 +1477,9 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, // Build an overload candidate set based on the functions we find. OverloadCandidateSet CandidateSet; - AddOverloadedCallCandidates(Function, UnqualifiedName, - ArgumentDependentLookup, HasExplicitTemplateArgs, - ExplicitTemplateArgs, NumExplicitTemplateArgs, + AddOverloadedCallCandidates(Fns, UnqualifiedName, + ArgumentDependentLookup, + (HasExplicitTemplateArgs ? &ExplicitTemplateArgs : 0), Args, NumArgs, CandidateSet, /*PartialOverloading=*/true); @@ -1968,8 +1957,10 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, if (!CDecl && FName->isStr("super")) { // "super" may be the name of a variable, in which case we are // probably calling an instance method. - OwningExprResult Super = ActOnDeclarationNameExpr(S, FNameLoc, FName, - false, 0, false); + CXXScopeSpec SS; + UnqualifiedId id; + id.setIdentifier(FName, FNameLoc); + OwningExprResult Super = ActOnIdExpression(S, SS, id, false, false); return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(), SelIdents, NumSelIdents); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b5109f8..520d7de 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -66,31 +66,68 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(DeclPtrTy Ptr) { /// and then return NULL. Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, Scope *S, const CXXScopeSpec *SS, - bool isClassName) { - // C++ [temp.res]p3: - // A qualified-id that refers to a type and in which the - // nested-name-specifier depends on a template-parameter (14.6.2) - // shall be prefixed by the keyword typename to indicate that the - // qualified-id denotes a type, forming an - // elaborated-type-specifier (7.1.5.3). - // - // We therefore do not perform any name lookup if the result would - // refer to a member of an unknown specialization. - if (SS && isUnknownSpecialization(*SS)) { - if (!isClassName) + bool isClassName, + TypeTy *ObjectTypePtr) { + // Determine where we will perform name lookup. + DeclContext *LookupCtx = 0; + if (ObjectTypePtr) { + QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr); + if (ObjectType->isRecordType()) + LookupCtx = computeDeclContext(ObjectType); + } else if (SS && SS->isSet()) { + LookupCtx = computeDeclContext(*SS, false); + + if (!LookupCtx) { + if (isDependentScopeSpecifier(*SS)) { + // C++ [temp.res]p3: + // A qualified-id that refers to a type and in which the + // nested-name-specifier depends on a template-parameter (14.6.2) + // shall be prefixed by the keyword typename to indicate that the + // qualified-id denotes a type, forming an + // elaborated-type-specifier (7.1.5.3). + // + // We therefore do not perform any name lookup if the result would + // refer to a member of an unknown specialization. + if (!isClassName) + return 0; + + // We know from the grammar that this name refers to a type, so build a + // TypenameType node to describe the type. + // FIXME: Record somewhere that this TypenameType node has no "typename" + // keyword associated with it. + return CheckTypenameType((NestedNameSpecifier *)SS->getScopeRep(), + II, SS->getRange()).getAsOpaquePtr(); + } + + return 0; + } + + if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS)) return 0; - - // We know from the grammar that this name refers to a type, so build a - // TypenameType node to describe the type. - // FIXME: Record somewhere that this TypenameType node has no "typename" - // keyword associated with it. - return CheckTypenameType((NestedNameSpecifier *)SS->getScopeRep(), - II, SS->getRange()).getAsOpaquePtr(); } - + LookupResult Result(*this, &II, NameLoc, LookupOrdinaryName); - LookupParsedName(Result, S, SS, false); - + if (LookupCtx) { + // Perform "qualified" name lookup into the declaration context we + // computed, which is either the type of the base of a member access + // expression or the declaration context associated with a prior + // nested-name-specifier. + LookupQualifiedName(Result, LookupCtx); + + if (ObjectTypePtr && Result.empty()) { + // C++ [basic.lookup.classref]p3: + // If the unqualified-id is ~type-name, the type-name is looked up + // in the context of the entire postfix-expression. If the type T of + // the object expression is of a class type C, the type-name is also + // looked up in the scope of class C. At least one of the lookups shall + // find a name that refers to (possibly cv-qualified) T. + LookupName(Result, S); + } + } else { + // Perform unqualified name lookup. + LookupName(Result, S); + } + NamedDecl *IIDecl = 0; switch (Result.getResultKind()) { case LookupResult::NotFound: @@ -364,37 +401,6 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { } bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) { - if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) { - // Look inside the overload set to determine if any of the declarations - // are in scope. (Possibly) build a new overload set containing only - // those declarations that are in scope. - OverloadedFunctionDecl *NewOvl = 0; - bool FoundInScope = false; - for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(), - FEnd = Ovl->function_end(); - F != FEnd; ++F) { - NamedDecl *FD = F->get(); - if (!isDeclInScope(FD, Ctx, S)) { - if (!NewOvl && F != Ovl->function_begin()) { - NewOvl = OverloadedFunctionDecl::Create(Context, - F->get()->getDeclContext(), - F->get()->getDeclName()); - D = NewOvl; - for (OverloadedFunctionDecl::function_iterator - First = Ovl->function_begin(); - First != F; ++First) - NewOvl->addOverload(*First); - } - } else { - FoundInScope = true; - if (NewOvl) - NewOvl->addOverload(*F); - } - } - - return FoundInScope; - } - return IdResolver.isDeclInScope(D, Ctx, Context, S); } @@ -644,7 +650,9 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { case 3: if (!TypeID->isStr("SEL")) break; - Context.setObjCSelType(Context.getTypeDeclType(New)); + Context.ObjCSelRedefinitionType = New->getUnderlyingType(); + // Install the built-in type for 'SEL', ignoring the current definition. + New->setTypeForDecl(Context.getObjCSelType().getTypePtr()); return; case 8: if (!TypeID->isStr("Protocol")) @@ -766,9 +774,6 @@ struct GNUCompatibleParamWarning { /// /// Returns true if there was an error, false otherwise. bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { - assert(!isa<OverloadedFunctionDecl>(OldD) && - "Cannot merge with an overloaded function declaration"); - // Verify the old decl was also a function. FunctionDecl *Old = 0; if (FunctionTemplateDecl *OldFunctionTemplate @@ -1718,22 +1723,26 @@ DeclarationName Sema::GetNameForDeclarator(Declarator &D) { } /// \brief Retrieves the canonicalized name from a parsed unqualified-id. -DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) { +DeclarationName Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { switch (Name.getKind()) { case UnqualifiedId::IK_Identifier: return DeclarationName(Name.Identifier); case UnqualifiedId::IK_OperatorFunctionId: return Context.DeclarationNames.getCXXOperatorName( - Name.OperatorFunctionId.Operator); - + Name.OperatorFunctionId.Operator); + + case UnqualifiedId::IK_LiteralOperatorId: + return Context.DeclarationNames.getCXXLiteralOperatorName( + Name.Identifier); + case UnqualifiedId::IK_ConversionFunctionId: { QualType Ty = GetTypeFromParser(Name.ConversionFunctionId); if (Ty.isNull()) return DeclarationName(); return Context.DeclarationNames.getCXXConversionFunctionName( - Context.getCanonicalType(Ty)); + Context.getCanonicalType(Ty)); } case UnqualifiedId::IK_ConstructorName: { @@ -1742,7 +1751,7 @@ DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) { return DeclarationName(); return Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(Ty)); + Context.getCanonicalType(Ty)); } case UnqualifiedId::IK_DestructorName: { @@ -2194,8 +2203,6 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, if (!PrevDecl) return 0; - // FIXME: PrevDecl could be an OverloadedFunctionDecl, in which - // case we need to check each of the overloaded functions. if (!PrevDecl->hasLinkage()) return false; @@ -2364,8 +2371,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast<StringLiteral>(E); - NewVD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(), - SE->getByteLength()))); + NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getString())); } // Don't consider existing declarations that are in a different @@ -2548,10 +2554,22 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *UserData) { RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); - + FindOverriddenMethodData *Data = reinterpret_cast<FindOverriddenMethodData*>(UserData); - for (Path.Decls = BaseRecord->lookup(Data->Method->getDeclName()); + + DeclarationName Name = Data->Method->getDeclName(); + + // FIXME: Do we care about other names here too? + if (Name.getNameKind() == DeclarationName::CXXDestructorName) { + // We really want to find the base class constructor here. + QualType T = Data->S->Context.getTypeDeclType(BaseRecord); + CanQualType CT = Data->S->Context.getCanonicalType(T); + + Name = Data->S->Context.DeclarationNames.getCXXDestructorName(CT); + } + + for (Path.Decls = BaseRecord->lookup(Name); Path.Decls.first != Path.Decls.second; ++Path.Decls.first) { if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*Path.Decls.first)) { @@ -2576,7 +2594,8 @@ void Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { E = Paths.found_decls_end(); I != E; ++I) { if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) { if (!CheckOverridingFunctionReturnType(MD, OldMD) && - !CheckOverridingFunctionExceptionSpec(MD, OldMD)) + !CheckOverridingFunctionExceptionSpec(MD, OldMD) && + !CheckOverridingFunctionAttributes(MD, OldMD)) MD->addOverriddenMethod(OldMD); } } @@ -2846,7 +2865,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewFD->setAccess(AS_public); } - if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD)) AddOverriddenMethods(cast<CXXRecordDecl>(DC), NewMD); @@ -2869,8 +2887,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast<StringLiteral>(E); - NewFD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(), - SE->getByteLength()))); + NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getString())); } // Copy the parameter declarations from the declarator D to the function @@ -2935,10 +2952,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // If the declarator is a template-id, translate the parser's template // argument list into our AST format. bool HasExplicitTemplateArgs = false; - llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; - SourceLocation LAngleLoc, RAngleLoc; + TemplateArgumentListInfo TemplateArgs; if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { TemplateIdAnnotation *TemplateId = D.getName().TemplateId; + TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc); + TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc); ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), TemplateId->NumArgs); @@ -2947,8 +2965,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, TemplateArgsPtr.release(); HasExplicitTemplateArgs = true; - LAngleLoc = TemplateId->LAngleLoc; - RAngleLoc = TemplateId->RAngleLoc; if (FunctionTemplate) { // FIXME: Diagnose function template with explicit template @@ -2970,9 +2986,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } if (isFunctionTemplateSpecialization) { - if (CheckFunctionTemplateSpecialization(NewFD, HasExplicitTemplateArgs, - LAngleLoc, TemplateArgs.data(), - TemplateArgs.size(), RAngleLoc, + if (CheckFunctionTemplateSpecialization(NewFD, + (HasExplicitTemplateArgs ? &TemplateArgs : 0), Previous)) NewFD->setInvalidDecl(); } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD) && @@ -2988,6 +3003,16 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, Previous.getResultKind() != LookupResult::FoundOverloaded) && "previous declaration set still overloaded"); + // If we have a function template, check the template parameter + // list. This will check and merge default template arguments. + if (FunctionTemplate) { + FunctionTemplateDecl *PrevTemplate = FunctionTemplate->getPreviousDeclaration(); + CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(), + PrevTemplate? PrevTemplate->getTemplateParameters() : 0, + D.getDeclSpec().isFriendSpecified()? TPC_FriendFunctionTemplate + : TPC_FunctionTemplate); + } + if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) { // An out-of-line member function declaration must also be a // definition (C++ [dcl.meaning]p1). diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index c96ab46..b2124fe 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -177,9 +177,10 @@ static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, // Special case where the argument is a template id. if (Attr.getParameterName()) { - sizeExpr = S.ActOnDeclarationNameExpr(scope, Attr.getLoc(), - Attr.getParameterName(), - false, 0, false).takeAs<Expr>(); + CXXScopeSpec SS; + UnqualifiedId id; + id.setIdentifier(Attr.getParameterName(), Attr.getLoc()); + sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs<Expr>(); } else { // check the attribute arguments. if (Attr.getNumArgs() != 1) { @@ -410,12 +411,9 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - const char *Alias = Str->getStrData(); - unsigned AliasLen = Str->getByteLength(); - // FIXME: check if target symbol exists in current file - d->addAttr(::new (S.Context) AliasAttr(std::string(Alias, AliasLen))); + d->addAttr(::new (S.Context) AliasAttr(Str->getString())); } static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, @@ -464,7 +462,9 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr, if (!isFunctionOrMethod(d) && !isa<BlockDecl>(d)) { ValueDecl *VD = dyn_cast<ValueDecl>(d); if (VD == 0 || !VD->getType()->isBlockPointerType()) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + S.Diag(Attr.getLoc(), + Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type + : diag::warn_attribute_wrong_decl_type) << Attr.getName() << 0 /*function*/; return false; } @@ -484,6 +484,15 @@ static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, d->addAttr(::new (S.Context) AnalyzerNoReturnAttr()); } +static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << 8; /*function, method, or parameter*/ + return; + } + // FIXME: Actually store the attribute on the declaration +} + static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 0) { @@ -994,12 +1003,10 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - std::string SectionStr(SE->getStrData(), SE->getByteLength()); - // If the target wants to validate the section specifier, make it happen. - std::string Error = S.Context.Target.isValidSectionSpecifier(SectionStr); + std::string Error = S.Context.Target.isValidSectionSpecifier(SE->getString()); if (Error.empty()) { - D->addAttr(::new (S.Context) SectionAttr(SectionStr)); + D->addAttr(::new (S.Context) SectionAttr(SE->getString())); return; } @@ -1506,8 +1513,7 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate"; return; } - d->addAttr(::new (S.Context) AnnotateAttr(std::string(SE->getStrData(), - SE->getByteLength()))); + d->addAttr(::new (S.Context) AnnotateAttr(SE->getString())); } static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1516,6 +1522,10 @@ static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; return; } + + //FIXME: The C++0x version of this attribute has more limited applicabilty + // than GNU's, and should error out when it is used to specify a + // weaker alignment, rather than being silently ignored. unsigned Align = 0; if (Attr.getNumArgs() == 0) { @@ -1794,6 +1804,108 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue())); } +static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<CXXRecordDecl>(d) + && (!isa<CXXMethodDecl>(d) || !cast<CXXMethodDecl>(d)->isVirtual())) { + S.Diag(Attr.getLoc(), + Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type + : diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 7 /*virtual method or class*/; + return; + } + + // FIXME: Conform to C++0x redeclaration rules. + + if (d->getAttr<FinalAttr>()) { + S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "final"; + return; + } + + d->addAttr(::new (S.Context) FinalAttr()); +} + +//===----------------------------------------------------------------------===// +// C++0x member checking attributes +//===----------------------------------------------------------------------===// + +static void HandleBaseCheckAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<CXXRecordDecl>(d)) { + S.Diag(Attr.getLoc(), + Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type + : diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 9 /*class*/; + return; + } + + if (d->getAttr<BaseCheckAttr>()) { + S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "base_check"; + return; + } + + d->addAttr(::new (S.Context) BaseCheckAttr()); +} + +static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<RecordDecl>(d->getDeclContext())) { + // FIXME: It's not the type that's the problem + S.Diag(Attr.getLoc(), + Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type + : diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 11 /*member*/; + return; + } + + // FIXME: Conform to C++0x redeclaration rules. + + if (d->getAttr<HidingAttr>()) { + S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "hiding"; + return; + } + + d->addAttr(::new (S.Context) HidingAttr()); +} + +static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<CXXMethodDecl>(d) || !cast<CXXMethodDecl>(d)->isVirtual()) { + // FIXME: It's not the type that's the problem + S.Diag(Attr.getLoc(), + Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type + : diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 10 /*virtual method*/; + return; + } + + // FIXME: Conform to C++0x redeclaration rules. + + if (d->getAttr<OverrideAttr>()) { + S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "override"; + return; + } + + d->addAttr(::new (S.Context) OverrideAttr()); +} + //===----------------------------------------------------------------------===// // Checker-specific attribute handlers. //===----------------------------------------------------------------------===// @@ -1841,7 +1953,8 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr, /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if /// the attribute applies to decls. If the attribute is a type attribute, just -/// silently ignore it. +/// silently ignore it if a GNU attribute. FIXME: Applying a C++0x attribute to +/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4). static void ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, Sema &S) { if (Attr.isDeclspecAttribute()) @@ -1854,31 +1967,37 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, // Ignore these, these are type attributes, handled by // ProcessTypeAttributes. break; - case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break; - case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break; + case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break; + case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break; case AttributeList::AT_always_inline: HandleAlwaysInlineAttr (D, Attr, S); break; case AttributeList::AT_analyzer_noreturn: HandleAnalyzerNoReturnAttr (D, Attr, S); break; - case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break; - case AttributeList::AT_cdecl: HandleCDeclAttr (D, Attr, S); break; - case AttributeList::AT_constructor: HandleConstructorAttr(D, Attr, S); break; - case AttributeList::AT_deprecated: HandleDeprecatedAttr(D, Attr, S); break; - case AttributeList::AT_destructor: HandleDestructorAttr(D, Attr, S); break; - case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break; - case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break; + case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break; + case AttributeList::AT_base_check: HandleBaseCheckAttr (D, Attr, S); break; + case AttributeList::AT_carries_dependency: + HandleDependencyAttr (D, Attr, S); break; + case AttributeList::AT_cdecl: HandleCDeclAttr (D, Attr, S); break; + case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break; + case AttributeList::AT_deprecated: HandleDeprecatedAttr (D, Attr, S); break; + case AttributeList::AT_destructor: HandleDestructorAttr (D, Attr, S); break; + case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break; + case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break; case AttributeList::AT_ext_vector_type: HandleExtVectorTypeAttr(scope, D, Attr, S); break; - case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break; - case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; - case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break; - case AttributeList::AT_gnu_inline: HandleGNUInlineAttr(D, Attr, S); break; - case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break; - case AttributeList::AT_malloc: HandleMallocAttr (D, Attr, S); break; - case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break; - case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break; - case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break; + case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break; + case AttributeList::AT_final: HandleFinalAttr (D, Attr, S); break; + case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; + case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break; + case AttributeList::AT_gnu_inline: HandleGNUInlineAttr (D, Attr, S); break; + case AttributeList::AT_hiding: HandleHidingAttr (D, Attr, S); break; + case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break; + case AttributeList::AT_malloc: HandleMallocAttr (D, Attr, S); break; + case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break; + case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break; + case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break; + case AttributeList::AT_override: HandleOverrideAttr (D, Attr, S); break; // Checker-specific. case AttributeList::AT_ns_returns_retained: @@ -1888,18 +2007,18 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_reqd_wg_size: HandleReqdWorkGroupSize(D, Attr, S); break; - case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; - case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break; - case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break; - case AttributeList::AT_unavailable: HandleUnavailableAttr(D, Attr, S); break; - case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break; - case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break; - case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break; - case AttributeList::AT_visibility: HandleVisibilityAttr(D, Attr, S); break; + case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; + case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break; + case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break; + case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break; + case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break; + case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break; + case AttributeList::AT_vector_size: HandleVectorSizeAttr (D, Attr, S); break; + case AttributeList::AT_visibility: HandleVisibilityAttr (D, Attr, S); break; case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S); break; - case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break; - case AttributeList::AT_weak_import: HandleWeakImportAttr(D, Attr, S); break; + case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break; + case AttributeList::AT_weak_import: HandleWeakImportAttr (D, Attr, S); break; case AttributeList::AT_transparent_union: HandleTransparentUnionAttr(D, Attr, S); break; @@ -1907,15 +2026,15 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, HandleObjCExceptionAttr(D, Attr, S); break; case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break; - case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break; - case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break; - case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break; - case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break; - case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break; - case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break; - case AttributeList::AT_nodebug: HandleNoDebugAttr (D, Attr, S); break; - case AttributeList::AT_noinline: HandleNoInlineAttr (D, Attr, S); break; - case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break; + case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break; + case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break; + case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break; + case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break; + case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break; + case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break; + case AttributeList::AT_nodebug: HandleNoDebugAttr (D, Attr, S); break; + case AttributeList::AT_noinline: HandleNoInlineAttr (D, Attr, S); break; + case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break; case AttributeList::IgnoredAttribute: case AttributeList::AT_no_instrument_function: // Interacts with -pg. // Just ignore diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index bda1a69..f161cb5 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -24,8 +24,6 @@ #include "clang/Basic/PartialDiagnostic.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Support/Compiler.h" -#include <algorithm> // for std::equal #include <map> #include <set> @@ -41,7 +39,7 @@ namespace { /// contains any ill-formed subexpressions. For example, this will /// diagnose the use of local variables or parameters within the /// default argument expression. - class VISIBILITY_HIDDEN CheckDefaultArgumentVisitor + class CheckDefaultArgumentVisitor : public StmtVisitor<CheckDefaultArgumentVisitor, bool> { Expr *DefaultArg; Sema *S; @@ -354,9 +352,8 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { if (CheckEquivalentExceptionSpec( Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(), - New->getType()->getAs<FunctionProtoType>(), New->getLocation())) { + New->getType()->getAs<FunctionProtoType>(), New->getLocation())) Invalid = true; - } return Invalid; } @@ -489,6 +486,13 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, Class->setEmpty(false); if (CXXBaseDecl->isPolymorphic()) Class->setPolymorphic(true); + // C++0x CWG Issue #817 indicates that [[final]] classes shouldn't be bases. + if (CXXBaseDecl->hasAttr<FinalAttr>()) { + Diag(BaseLoc, diag::err_final_base) << BaseType.getAsString(); + Diag(CXXBaseDecl->getLocation(), diag::note_previous_class_decl) + << BaseType.getAsString(); + return 0; + } // C++ [dcl.init.aggr]p1: // An aggregate is [...] a class with [...] no base classes [...]. @@ -783,7 +787,8 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { Sema::DeclPtrTy Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, - ExprTy *BW, ExprTy *InitExpr, bool Deleted) { + ExprTy *BW, ExprTy *InitExpr, bool IsDefinition, + bool Deleted) { const DeclSpec &DS = D.getDeclSpec(); DeclarationName Name = GetNameForDeclarator(D); Expr *BitWidth = static_cast<Expr*>(BW); @@ -865,7 +870,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, AS); assert(Member && "HandleField never returns null"); } else { - Member = HandleDeclarator(S, D, move(TemplateParameterLists), false) + Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition) .getAs<Decl>(); if (!Member) { if (BitWidth) DeleteExpr(BitWidth); @@ -1708,7 +1713,7 @@ void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) { namespace { /// PureVirtualMethodCollector - traverses a class and its superclasses /// and determines if it has any pure virtual methods. - class VISIBILITY_HIDDEN PureVirtualMethodCollector { + class PureVirtualMethodCollector { ASTContext &Context; public: @@ -1855,7 +1860,7 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, } namespace { - class VISIBILITY_HIDDEN AbstractClassUsageDiagnoser + class AbstractClassUsageDiagnoser : public DeclVisitor<AbstractClassUsageDiagnoser, bool> { Sema &SemaRef; CXXRecordDecl *AbstractClass; @@ -2164,6 +2169,8 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { Destructor->setImplicit(); Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); ClassDecl->addDecl(Destructor); + + AddOverriddenMethods(ClassDecl, Destructor); } } @@ -2360,9 +2367,9 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { ClassDecl->addedConstructor(Context, Constructor); } -/// CheckDestructor - Checks a fully-formed destructor for -/// well-formedness, issuing any diagnostics required. -void Sema::CheckDestructor(CXXDestructorDecl *Destructor) { +/// CheckDestructor - Checks a fully-formed destructor for well-formedness, +/// issuing any diagnostics required. Returns true on error. +bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { CXXRecordDecl *RD = Destructor->getParent(); if (Destructor->isVirtual()) { @@ -2377,9 +2384,13 @@ void Sema::CheckDestructor(CXXDestructorDecl *Destructor) { FunctionDecl *OperatorDelete = 0; DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Delete); - if (!FindDeallocationFunction(Loc, RD, Name, OperatorDelete)) - Destructor->setOperatorDelete(OperatorDelete); + if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete)) + return true; + + Destructor->setOperatorDelete(OperatorDelete); } + + return false; } static inline bool @@ -2594,16 +2605,8 @@ Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { if (FunctionTemplateDecl *ConversionTemplate = Conversion->getDescribedFunctionTemplate()) ExpectedPrevDecl = ConversionTemplate->getPreviousDeclaration(); - OverloadedFunctionDecl *Conversions = ClassDecl->getConversionFunctions(); - for (OverloadedFunctionDecl::function_iterator - Conv = Conversions->function_begin(), - ConvEnd = Conversions->function_end(); - Conv != ConvEnd; ++Conv) { - if (*Conv == ExpectedPrevDecl) { - *Conv = Conversion; - return DeclPtrTy::make(Conversion); - } - } + if (ClassDecl->replaceConversion(ExpectedPrevDecl, Conversion)) + return DeclPtrTy::make(Conversion); assert(Conversion->isInvalidDecl() && "Conversion should not get here."); } else if (FunctionTemplateDecl *ConversionTemplate = Conversion->getDescribedFunctionTemplate()) @@ -2723,6 +2726,14 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, return DeclPtrTy::make(Namespc); } +/// getNamespaceDecl - Returns the namespace a decl represents. If the decl +/// is a namespace alias, returns the namespace it points to. +static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { + if (NamespaceAliasDecl *AD = dyn_cast_or_null<NamespaceAliasDecl>(D)) + return AD->getNamespace(); + return dyn_cast_or_null<NamespaceDecl>(D); +} + /// ActOnFinishNamespaceDef - This callback is called after a namespace is /// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef. void Sema::ActOnFinishNamespaceDef(DeclPtrTy D, SourceLocation RBrace) { @@ -2754,9 +2765,9 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, return DeclPtrTy(); if (!R.empty()) { - NamedDecl *NS = R.getFoundDecl(); - // FIXME: Namespace aliases! - assert(isa<NamespaceDecl>(NS) && "expected namespace decl"); + NamedDecl *Named = R.getFoundDecl(); + assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named)) + && "expected namespace decl"); // C++ [namespace.udir]p1: // A using-directive specifies that the names in the nominated // namespace can be used in the scope in which the @@ -2769,18 +2780,15 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, // Find enclosing context containing both using-directive and // nominated namespace. + NamespaceDecl *NS = getNamespaceDecl(Named); DeclContext *CommonAncestor = cast<DeclContext>(NS); while (CommonAncestor && !CommonAncestor->Encloses(CurContext)) CommonAncestor = CommonAncestor->getParent(); - UDir = UsingDirectiveDecl::Create(Context, - CurContext, UsingLoc, - NamespcLoc, + UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc, SS.getRange(), (NestedNameSpecifier *)SS.getScopeRep(), - IdentLoc, - cast<NamespaceDecl>(NS), - CommonAncestor); + IdentLoc, Named, CommonAncestor); PushUsingDirective(S, UDir); } else { Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); @@ -2817,6 +2825,7 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, switch (Name.getKind()) { case UnqualifiedId::IK_Identifier: case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedId::IK_LiteralOperatorId: case UnqualifiedId::IK_ConversionFunctionId: break; @@ -3007,14 +3016,6 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, return UD; } -/// getNamespaceDecl - Returns the namespace a decl represents. If the decl -/// is a namespace alias, returns the namespace it points to. -static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { - if (NamespaceAliasDecl *AD = dyn_cast_or_null<NamespaceAliasDecl>(D)) - return AD->getNamespace(); - return dyn_cast_or_null<NamespaceDecl>(D); -} - Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, SourceLocation AliasLoc, @@ -3074,8 +3075,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); if (SetBaseOrMemberInitializers(Constructor, 0, 0, true)) { - Diag(CurrentLocation, diag::note_ctor_synthesized_at) - << Context.getTagDeclType(ClassDecl); + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXDefaultConstructor << Context.getTagDeclType(ClassDecl); Constructor->setInvalidDecl(); } else { Constructor->setUsed(); @@ -3127,6 +3128,17 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, } } } + + // FIXME: If CheckDestructor fails, we should emit a note about where the + // implicit destructor was needed. + if (CheckDestructor(Destructor)) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXDestructor << Context.getTagDeclType(ClassDecl); + + Destructor->setInvalidDecl(); + return; + } + Destructor->setUsed(); } @@ -3292,6 +3304,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, unsigned NumExprs = ExprArgs.size(); Expr **Exprs = (Expr **)ExprArgs.release(); + MarkDeclarationReferenced(ConstructLoc, Constructor); return Owned(CXXConstructExpr::Create(Context, DeclInitType, Constructor, Elidable, Exprs, NumExprs)); } @@ -3305,6 +3318,7 @@ Sema::BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Constructor, unsigned NumExprs = Args.size(); Expr **Exprs = (Expr **)Args.release(); + MarkDeclarationReferenced(TyBeginLoc, Constructor); return Owned(new (Context) CXXTemporaryObjectExpr(Context, Constructor, Ty, TyBeginLoc, Exprs, NumExprs, RParenLoc)); @@ -3490,7 +3504,8 @@ static void AddConstructorInitializationCandidates(Sema &SemaRef, Constructor->isConvertingConstructor(/*AllowExplicit=*/false)) || (Kind == Sema::IK_Default && Constructor->isDefaultConstructor())) { if (ConstructorTmpl) - SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0, + SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl, + /*ExplicitArgs*/ 0, Args, NumArgs, CandidateSet); else SemaRef.AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet); @@ -3612,10 +3627,13 @@ Sema::PerformInitializationByConstructor(QualType ClassType, Diag(Loc, diag::err_ovl_deleted_init) << Best->Function->isDeleted() << InitEntity << Range; - else + else { + const CXXRecordDecl *RD = + cast<CXXRecordDecl>(ClassType->getAs<RecordType>()->getDecl()); Diag(Loc, diag::err_ovl_deleted_init) << Best->Function->isDeleted() - << InitEntity << Range; + << RD->getDeclName() << Range; + } PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); return 0; } @@ -3646,58 +3664,22 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, = Constructor->getType()->getAs<FunctionProtoType>(); assert(Proto && "Constructor without a prototype?"); unsigned NumArgsInProto = Proto->getNumArgs(); - unsigned NumArgsToCheck = NumArgs; // If too few arguments are available, we'll fill in the rest with defaults. - if (NumArgs < NumArgsInProto) { - NumArgsToCheck = NumArgsInProto; + if (NumArgs < NumArgsInProto) ConvertedArgs.reserve(NumArgsInProto); - } else { + else ConvertedArgs.reserve(NumArgs); - if (NumArgs > NumArgsInProto) - NumArgsToCheck = NumArgsInProto; - } - - // Convert arguments - for (unsigned i = 0; i != NumArgsToCheck; i++) { - QualType ProtoArgType = Proto->getArgType(i); - - Expr *Arg; - if (i < NumArgs) { - Arg = Args[i]; - - // Pass the argument. - if (PerformCopyInitialization(Arg, ProtoArgType, "passing")) - return true; - - Args[i] = 0; - } else { - ParmVarDecl *Param = Constructor->getParamDecl(i); - - OwningExprResult DefArg = BuildCXXDefaultArgExpr(Loc, Constructor, Param); - if (DefArg.isInvalid()) - return true; - - Arg = DefArg.takeAs<Expr>(); - } - - ConvertedArgs.push_back(Arg); - } - - // If this is a variadic call, handle args passed through "...". - if (Proto->isVariadic()) { - // Promote the arguments (C99 6.5.2.2p7). - for (unsigned i = NumArgsInProto; i != NumArgs; i++) { - Expr *Arg = Args[i]; - if (DefaultVariadicArgumentPromotion(Arg, VariadicConstructor)) - return true; - - ConvertedArgs.push_back(Arg); - Args[i] = 0; - } - } - - return false; + + VariadicCallType CallType = + Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply; + llvm::SmallVector<Expr *, 8> AllArgs; + bool Invalid = GatherArgumentsForCall(Loc, Constructor, + Proto, 0, Args, NumArgs, AllArgs, + CallType); + for (unsigned i =0, size = AllArgs.size(); i < size; i++) + ConvertedArgs.push_back(AllArgs[i]); + return Invalid; } /// CompareReferenceRelationship - Compare the two types T1 and T2 to @@ -3888,18 +3870,17 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl()); OverloadCandidateSet CandidateSet; - OverloadedFunctionDecl *Conversions + const UnresolvedSet *Conversions = T2RecordDecl->getVisibleConversionFunctions(); - for (OverloadedFunctionDecl::function_iterator Func - = Conversions->function_begin(); - Func != Conversions->function_end(); ++Func) { + for (UnresolvedSet::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { FunctionTemplateDecl *ConvTemplate - = dyn_cast<FunctionTemplateDecl>(*Func); + = dyn_cast<FunctionTemplateDecl>(*I); CXXConversionDecl *Conv; if (ConvTemplate) Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); else - Conv = cast<CXXConversionDecl>(*Func); + Conv = cast<CXXConversionDecl>(*I); // If the conversion function doesn't return a reference type, // it can't be considered for this conversion. @@ -4896,6 +4877,19 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, return false; } +bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New, + const CXXMethodDecl *Old) +{ + if (Old->hasAttr<FinalAttr>()) { + Diag(New->getLocation(), diag::err_final_function_overridden) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; + } + + return false; +} + /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an /// initializer for the declaration 'Dcl'. /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a @@ -4942,3 +4936,39 @@ void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) { assert(S->getEntity() == D->getDeclContext() && "Context imbalance!"); ExitDeclaratorContext(S); } + +/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a +/// C++ if/switch/while/for statement. +/// e.g: "if (int x = f()) {...}" +Action::DeclResult +Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { + // C++ 6.4p2: + // The declarator shall not specify a function or an array. + // The type-specifier-seq shall not contain typedef and shall not declare a + // new class or enumeration. + assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && + "Parser allowed 'typedef' as storage class of condition decl."); + + DeclaratorInfo *DInfo = 0; + TagDecl *OwnedTag = 0; + QualType Ty = GetTypeForDeclarator(D, S, &DInfo, &OwnedTag); + + if (Ty->isFunctionType()) { // The declarator shall not specify a function... + // We exit without creating a CXXConditionDeclExpr because a FunctionDecl + // would be created and CXXConditionDeclExpr wants a VarDecl. + Diag(D.getIdentifierLoc(), diag::err_invalid_use_of_function_type) + << D.getSourceRange(); + return DeclResult(); + } else if (OwnedTag && OwnedTag->isDefinition()) { + // The type-specifier-seq shall not declare a new class or enumeration. + Diag(OwnedTag->getLocation(), diag::err_type_defined_in_condition); + } + + DeclPtrTy Dcl = ActOnDeclarator(S, D); + if (!Dcl) + return DeclResult(); + + VarDecl *VD = cast<VarDecl>(Dcl.getAs<Decl>()); + VD->setDeclaredInCondition(true); + return Dcl; +} diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 4f08ffe..f653cf6 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -152,9 +152,10 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, ++sentinel; } Expr *sentinelExpr = Args[sentinel]; - if (sentinelExpr && (!sentinelExpr->getType()->isPointerType() || - !sentinelExpr->isNullPointerConstant(Context, - Expr::NPC_ValueDependentIsNull))) { + if (sentinelExpr && (!isa<GNUNullExpr>(sentinelExpr) && + (!sentinelExpr->getType()->isPointerType() || + !sentinelExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)))) { Diag(Loc, diag::warn_missing_sentinel) << isMethod; Diag(D->getLocation(), diag::note_sentinel_here) << isMethod; } @@ -415,7 +416,6 @@ static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock, /// BuildDeclRefExpr - Build a DeclRefExpr. Sema::OwningExprResult Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, - bool TypeDependent, bool ValueDependent, const CXXScopeSpec *SS) { if (Context.getCanonicalType(Ty) == Context.UndeducedAutoTy) { Diag(Loc, @@ -443,8 +443,7 @@ Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, return Owned(DeclRefExpr::Create(Context, SS? (NestedNameSpecifier *)SS->getScopeRep() : 0, SS? SS->getRange() : SourceRange(), - D, Loc, - Ty, TypeDependent, ValueDependent)); + D, Loc, Ty)); } /// getObjectForAnonymousRecordDecl - Retrieve the (unnamed) field or @@ -616,204 +615,210 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, return Owned(Result); } -Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, - const CXXScopeSpec &SS, - UnqualifiedId &Name, - bool HasTrailingLParen, - bool IsAddressOfOperand) { - if (Name.getKind() == UnqualifiedId::IK_TemplateId) { - ASTTemplateArgsPtr TemplateArgsPtr(*this, - Name.TemplateId->getTemplateArgs(), - Name.TemplateId->NumArgs); - return ActOnTemplateIdExpr(SS, - TemplateTy::make(Name.TemplateId->Template), - Name.TemplateId->TemplateNameLoc, - Name.TemplateId->LAngleLoc, - TemplateArgsPtr, - Name.TemplateId->RAngleLoc); +/// Decomposes the given name into a DeclarationName, its location, and +/// possibly a list of template arguments. +/// +/// If this produces template arguments, it is permitted to call +/// DecomposeTemplateName. +/// +/// This actually loses a lot of source location information for +/// non-standard name kinds; we should consider preserving that in +/// some way. +static void DecomposeUnqualifiedId(Sema &SemaRef, + const UnqualifiedId &Id, + TemplateArgumentListInfo &Buffer, + DeclarationName &Name, + SourceLocation &NameLoc, + const TemplateArgumentListInfo *&TemplateArgs) { + if (Id.getKind() == UnqualifiedId::IK_TemplateId) { + Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc); + Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc); + + ASTTemplateArgsPtr TemplateArgsPtr(SemaRef, + Id.TemplateId->getTemplateArgs(), + Id.TemplateId->NumArgs); + SemaRef.translateTemplateArguments(TemplateArgsPtr, Buffer); + TemplateArgsPtr.release(); + + TemplateName TName = + Sema::TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>(); + + Name = SemaRef.Context.getNameForTemplate(TName); + NameLoc = Id.TemplateId->TemplateNameLoc; + TemplateArgs = &Buffer; + } else { + Name = SemaRef.GetNameFromUnqualifiedId(Id); + NameLoc = Id.StartLocation; + TemplateArgs = 0; } - - // FIXME: We lose a bunch of source information by doing this. Later, - // we'll want to merge ActOnDeclarationNameExpr's logic into - // ActOnIdExpression. - return ActOnDeclarationNameExpr(S, - Name.StartLocation, - GetNameFromUnqualifiedId(Name), - HasTrailingLParen, - &SS, - IsAddressOfOperand); } -/// ActOnDeclarationNameExpr - The parser has read some kind of name -/// (e.g., a C++ id-expression (C++ [expr.prim]p1)). This routine -/// performs lookup on that name and returns an expression that refers -/// to that name. This routine isn't directly called from the parser, -/// because the parser doesn't know about DeclarationName. Rather, -/// this routine is called by ActOnIdExpression, which contains a -/// parsed UnqualifiedId. +/// Decompose the given template name into a list of lookup results. /// -/// HasTrailingLParen indicates whether this identifier is used in a -/// function call context. LookupCtx is only used for a C++ -/// qualified-id (foo::bar) to indicate the class or namespace that -/// the identifier must be a member of. -/// -/// isAddressOfOperand means that this expression is the direct operand -/// of an address-of operator. This matters because this is the only -/// situation where a qualified name referencing a non-static member may -/// appear outside a member function of this class. -Sema::OwningExprResult -Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, - DeclarationName Name, bool HasTrailingLParen, - const CXXScopeSpec *SS, - bool isAddressOfOperand) { - // Could be enum-constant, value decl, instance variable, etc. - if (SS && SS->isInvalid()) - return ExprError(); +/// The unqualified ID must name a non-dependent template, which can +/// be more easily tested by checking whether DecomposeUnqualifiedId +/// found template arguments. +static void DecomposeTemplateName(LookupResult &R, const UnqualifiedId &Id) { + assert(Id.getKind() == UnqualifiedId::IK_TemplateId); + TemplateName TName = + Sema::TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>(); + + if (TemplateDecl *TD = TName.getAsTemplateDecl()) + R.addDecl(TD); + else if (OverloadedFunctionDecl *OD + = TName.getAsOverloadedFunctionDecl()) + for (OverloadIterator I(OD), E; I != E; ++I) + R.addDecl(*I); + + R.resolveKind(); +} - // C++ [temp.dep.expr]p3: - // An id-expression is type-dependent if it contains: - // -- a nested-name-specifier that contains a class-name that - // names a dependent type. - // FIXME: Member of the current instantiation. - if (SS && isDependentScopeSpecifier(*SS)) { - return Owned(new (Context) UnresolvedDeclRefExpr(Name, Context.DependentTy, - Loc, SS->getRange(), - static_cast<NestedNameSpecifier *>(SS->getScopeRep()), - isAddressOfOperand)); +static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) { + for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(), + E = Record->bases_end(); I != E; ++I) { + CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType()); + CanQual<RecordType> BaseRT = BaseT->getAs<RecordType>(); + if (!BaseRT) return false; + + CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl()); + if (!BaseRecord->isDefinition() || + !IsFullyFormedScope(SemaRef, BaseRecord)) + return false; } - LookupResult Lookup(*this, Name, Loc, LookupOrdinaryName); - LookupParsedName(Lookup, S, SS, true); + return true; +} + +/// Determines whether we can lookup this id-expression now or whether +/// we have to wait until template instantiation is complete. +static bool IsDependentIdExpression(Sema &SemaRef, const CXXScopeSpec &SS) { + DeclContext *DC = SemaRef.computeDeclContext(SS, false); + + // If the qualifier scope isn't computable, it's definitely dependent. + if (!DC) return true; - if (Lookup.isAmbiguous()) + // If the qualifier scope doesn't name a record, we can always look into it. + if (!isa<CXXRecordDecl>(DC)) return false; + + // We can't look into record types unless they're fully-formed. + if (!IsFullyFormedScope(SemaRef, cast<CXXRecordDecl>(DC))) return true; + + // We can always look into fully-formed record types, but if we're + // in a dependent but not fully-formed context, we can't decide + // whether the qualifier names a base class. We shouldn't be trying + // to decide that yet anyway, but we are, so we need to delay that + // decision. + CXXRecordDecl *CurRecord; + if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(SemaRef.CurContext)) + CurRecord = cast<CXXRecordDecl>(CurMethod->getParent()); + else + CurRecord = dyn_cast<CXXRecordDecl>(SemaRef.CurContext); + + return CurRecord && !IsFullyFormedScope(SemaRef, CurRecord); +} + +Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, + const CXXScopeSpec &SS, + UnqualifiedId &Id, + bool HasTrailingLParen, + bool isAddressOfOperand) { + assert(!(isAddressOfOperand && HasTrailingLParen) && + "cannot be direct & operand and have a trailing lparen"); + + if (SS.isInvalid()) return ExprError(); - NamedDecl *D = Lookup.getAsSingleDecl(Context); + TemplateArgumentListInfo TemplateArgsBuffer; + + // Decompose the UnqualifiedId into the following data. + DeclarationName Name; + SourceLocation NameLoc; + const TemplateArgumentListInfo *TemplateArgs; + DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer, + Name, NameLoc, TemplateArgs); - // If this reference is in an Objective-C method, then ivar lookup happens as - // well. IdentifierInfo *II = Name.getAsIdentifierInfo(); - if (II && getCurMethodDecl()) { - // There are two cases to handle here. 1) scoped lookup could have failed, - // in which case we should look for an ivar. 2) scoped lookup could have - // found a decl, but that decl is outside the current instance method (i.e. - // a global variable). In these two cases, we do a lookup for an ivar with - // this name, if the lookup sucedes, we replace it our current decl. - if (D == 0 || D->isDefinedOutsideFunctionOrMethod()) { - ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); - ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { - // Check if referencing a field with __attribute__((deprecated)). - if (DiagnoseUseOfDecl(IV, Loc)) - return ExprError(); - // If we're referencing an invalid decl, just return this as a silent - // error node. The error diagnostic was already emitted on the decl. - if (IV->isInvalidDecl()) - return ExprError(); + // C++ [temp.dep.expr]p3: + // An id-expression is type-dependent if it contains: + // -- a nested-name-specifier that contains a class-name that + // names a dependent type. + // Determine whether this is a member of an unknown specialization; + // we need to handle these differently. + if (SS.isSet() && IsDependentIdExpression(*this, SS)) { + bool CheckForImplicitMember = !isAddressOfOperand; - bool IsClsMethod = getCurMethodDecl()->isClassMethod(); - // If a class method attemps to use a free standing ivar, this is - // an error. - if (IsClsMethod && D && !D->isDefinedOutsideFunctionOrMethod()) - return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method) - << IV->getDeclName()); - // If a class method uses a global variable, even if an ivar with - // same name exists, use the global. - if (!IsClsMethod) { - if (IV->getAccessControl() == ObjCIvarDecl::Private && - ClassDeclared != IFace) - Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName(); - // FIXME: This should use a new expr for a direct reference, don't - // turn this into Self->ivar, just return a BareIVarExpr or something. - IdentifierInfo &II = Context.Idents.get("self"); - UnqualifiedId SelfName; - SelfName.setIdentifier(&II, SourceLocation()); - CXXScopeSpec SelfScopeSpec; - OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, - SelfName, false, false); - MarkDeclarationReferenced(Loc, IV); - return Owned(new (Context) - ObjCIvarRefExpr(IV, IV->getType(), Loc, - SelfExpr.takeAs<Expr>(), true, true)); - } - } - } else if (getCurMethodDecl()->isInstanceMethod()) { - // We should warn if a local variable hides an ivar. - ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); - ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { - if (IV->getAccessControl() != ObjCIvarDecl::Private || - IFace == ClassDeclared) - Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); - } - } - // Needed to implement property "super.method" notation. - if (D == 0 && II->isStr("super")) { - QualType T; + return ActOnDependentIdExpression(SS, Name, NameLoc, + CheckForImplicitMember, + TemplateArgs); + } - if (getCurMethodDecl()->isInstanceMethod()) - T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType( - getCurMethodDecl()->getClassInterface())); - else - T = Context.getObjCClassType(); - return Owned(new (Context) ObjCSuperExpr(Loc, T)); + // Perform the required lookup. + LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); + if (TemplateArgs) { + // Just re-use the lookup done by isTemplateName. + DecomposeTemplateName(R, Id); + } else { + LookupParsedName(R, S, &SS, true); + + // If this reference is in an Objective-C method, then we need to do + // some special Objective-C lookup, too. + if (!SS.isSet() && II && getCurMethodDecl()) { + OwningExprResult E(LookupInObjCMethod(R, S, II)); + if (E.isInvalid()) + return ExprError(); + + Expr *Ex = E.takeAs<Expr>(); + if (Ex) return Owned(Ex); } } + if (R.isAmbiguous()) + return ExprError(); + // Determine whether this name might be a candidate for // argument-dependent lookup. - bool ADL = getLangOptions().CPlusPlus && (!SS || !SS->isSet()) && - HasTrailingLParen; + bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen); - if (ADL && D == 0) { - // We've seen something of the form - // - // identifier( - // - // and we did not find any entity by the name - // "identifier". However, this identifier is still subject to - // argument-dependent lookup, so keep track of the name. - return Owned(new (Context) UnresolvedFunctionNameExpr(Name, - Context.OverloadTy, - Loc)); - } - - if (D == 0) { + if (R.empty() && !ADL) { // Otherwise, this could be an implicitly declared function reference (legal - // in C90, extension in C99). - if (HasTrailingLParen && II && - !getLangOptions().CPlusPlus) // Not in C++. - D = ImplicitlyDefineFunction(Loc, *II, S); - else { - // If this name wasn't predeclared and if this is not a function call, - // diagnose the problem. - if (SS && !SS->isEmpty()) - return ExprError(Diag(Loc, diag::err_no_member) - << Name << computeDeclContext(*SS, false) - << SS->getRange()); + // in C90, extension in C99, forbidden in C++). + if (HasTrailingLParen && II && !getLangOptions().CPlusPlus) { + NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S); + if (D) R.addDecl(D); + } + + // If this name wasn't predeclared and if this is not a function + // call, diagnose the problem. + if (R.empty()) { + if (!SS.isEmpty()) + return ExprError(Diag(NameLoc, diag::err_no_member) + << Name << computeDeclContext(SS, false) + << SS.getRange()); else if (Name.getNameKind() == DeclarationName::CXXOperatorName || + Name.getNameKind() == DeclarationName::CXXLiteralOperatorName || Name.getNameKind() == DeclarationName::CXXConversionFunctionName) - return ExprError(Diag(Loc, diag::err_undeclared_use) - << Name.getAsString()); + return ExprError(Diag(NameLoc, diag::err_undeclared_use) + << Name); else - return ExprError(Diag(Loc, diag::err_undeclared_var_use) << Name); + return ExprError(Diag(NameLoc, diag::err_undeclared_var_use) << Name); } } - if (VarDecl *Var = dyn_cast<VarDecl>(D)) { + // This is guaranteed from this point on. + assert(!R.empty() || ADL); + + if (VarDecl *Var = R.getAsSingle<VarDecl>()) { // Warn about constructs like: // if (void *X = foo()) { ... } else { X }. // In the else block, the pointer is always false. - // FIXME: In a template instantiation, we don't have scope - // information to check this property. if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) { Scope *CheckS = S; while (CheckS && CheckS->getControlParent()) { if (CheckS->isWithinElse() && CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) { - ExprError(Diag(Loc, diag::warn_value_always_zero) + ExprError(Diag(NameLoc, diag::warn_value_always_zero) << Var->getDeclName() << (Var->getType()->isPointerType()? 2 : Var->getType()->isBooleanType()? 1 : 0)); @@ -824,26 +829,174 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, CheckS = CheckS->getParent(); } } - } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) { + } else if (FunctionDecl *Func = R.getAsSingle<FunctionDecl>()) { if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) { // C99 DR 316 says that, if a function type comes from a // function definition (without a prototype), that type is only // used for checking compatibility. Therefore, when referencing // the function, we pretend that we don't have the full function // type. - if (DiagnoseUseOfDecl(Func, Loc)) + if (DiagnoseUseOfDecl(Func, NameLoc)) return ExprError(); QualType T = Func->getType(); QualType NoProtoType = T; if (const FunctionProtoType *Proto = T->getAs<FunctionProtoType>()) NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType()); - return BuildDeclRefExpr(Func, NoProtoType, Loc, false, false, SS); + return BuildDeclRefExpr(Func, NoProtoType, NameLoc, &SS); + } + } + + // &SomeClass::foo is an abstract member reference, regardless of + // the nature of foo, but &SomeClass::foo(...) is not. If this is + // *not* an abstract member reference, and any of the results is a + // class member (which necessarily means they're all class members), + // then we make an implicit member reference instead. + // + // This check considers all the same information as the "needs ADL" + // check, but there's no simple logical relationship other than the + // fact that they can never be simultaneously true. We could + // calculate them both in one pass if that proves important for + // performance. + if (!ADL) { + bool isAbstractMemberPointer = (isAddressOfOperand && !SS.isEmpty()); + + if (!isAbstractMemberPointer && !R.empty() && + isa<CXXRecordDecl>((*R.begin())->getDeclContext())) { + return BuildImplicitMemberReferenceExpr(SS, R, TemplateArgs); } } - return BuildDeclarationNameExpr(Loc, D, HasTrailingLParen, SS, isAddressOfOperand); + if (TemplateArgs) + return BuildTemplateIdExpr(SS, R, ADL, *TemplateArgs); + + return BuildDeclarationNameExpr(SS, R, ADL); +} + +/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified +/// declaration name, generally during template instantiation. +/// There's a large number of things which don't need to be done along +/// this path. +Sema::OwningExprResult +Sema::BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc) { + DeclContext *DC; + if (!(DC = computeDeclContext(SS, false)) || + DC->isDependentContext() || + RequireCompleteDeclContext(SS)) + return BuildDependentDeclRefExpr(SS, Name, NameLoc, 0); + + LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); + LookupQualifiedName(R, DC); + + if (R.isAmbiguous()) + return ExprError(); + + if (R.empty()) { + Diag(NameLoc, diag::err_no_member) << Name << DC << SS.getRange(); + return ExprError(); + } + + return BuildDeclarationNameExpr(SS, R, /*ADL*/ false); } + +/// LookupInObjCMethod - The parser has read a name in, and Sema has +/// detected that we're currently inside an ObjC method. Perform some +/// additional lookup. +/// +/// Ideally, most of this would be done by lookup, but there's +/// actually quite a lot of extra work involved. +/// +/// Returns a null sentinel to indicate trivial success. +Sema::OwningExprResult +Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, + IdentifierInfo *II) { + SourceLocation Loc = Lookup.getNameLoc(); + + // There are two cases to handle here. 1) scoped lookup could have failed, + // in which case we should look for an ivar. 2) scoped lookup could have + // found a decl, but that decl is outside the current instance method (i.e. + // a global variable). In these two cases, we do a lookup for an ivar with + // this name, if the lookup sucedes, we replace it our current decl. + + // If we're in a class method, we don't normally want to look for + // ivars. But if we don't find anything else, and there's an + // ivar, that's an error. + bool IsClassMethod = getCurMethodDecl()->isClassMethod(); + + bool LookForIvars; + if (Lookup.empty()) + LookForIvars = true; + else if (IsClassMethod) + LookForIvars = false; + else + LookForIvars = (Lookup.isSingleResult() && + Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()); + + if (LookForIvars) { + ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { + // Diagnose using an ivar in a class method. + if (IsClassMethod) + return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method) + << IV->getDeclName()); + + // If we're referencing an invalid decl, just return this as a silent + // error node. The error diagnostic was already emitted on the decl. + if (IV->isInvalidDecl()) + return ExprError(); + + // Check if referencing a field with __attribute__((deprecated)). + if (DiagnoseUseOfDecl(IV, Loc)) + return ExprError(); + + // Diagnose the use of an ivar outside of the declaring class. + if (IV->getAccessControl() == ObjCIvarDecl::Private && + ClassDeclared != IFace) + Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName(); + + // FIXME: This should use a new expr for a direct reference, don't + // turn this into Self->ivar, just return a BareIVarExpr or something. + IdentifierInfo &II = Context.Idents.get("self"); + UnqualifiedId SelfName; + SelfName.setIdentifier(&II, SourceLocation()); + CXXScopeSpec SelfScopeSpec; + OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, + SelfName, false, false); + MarkDeclarationReferenced(Loc, IV); + return Owned(new (Context) + ObjCIvarRefExpr(IV, IV->getType(), Loc, + SelfExpr.takeAs<Expr>(), true, true)); + } + } else if (getCurMethodDecl()->isInstanceMethod()) { + // We should warn if a local variable hides an ivar. + ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { + if (IV->getAccessControl() != ObjCIvarDecl::Private || + IFace == ClassDeclared) + Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); + } + } + + // Needed to implement property "super.method" notation. + if (Lookup.empty() && II->isStr("super")) { + QualType T; + + if (getCurMethodDecl()->isInstanceMethod()) + T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType( + getCurMethodDecl()->getClassInterface())); + else + T = Context.getObjCClassType(); + return Owned(new (Context) ObjCSuperExpr(Loc, T)); + } + + // Sentinel value saying that we didn't do anything special. + return Owned((Expr*) 0); +} + /// \brief Cast member's object to its own class if necessary. bool Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) { @@ -874,114 +1027,224 @@ Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) { /// \brief Build a MemberExpr AST node. static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, - const CXXScopeSpec *SS, NamedDecl *Member, - SourceLocation Loc, QualType Ty) { - if (SS && SS->isSet()) - return MemberExpr::Create(C, Base, isArrow, - (NestedNameSpecifier *)SS->getScopeRep(), - SS->getRange(), Member, Loc, - // FIXME: Explicit template argument lists - false, SourceLocation(), 0, 0, SourceLocation(), - Ty); - - return new (C) MemberExpr(Base, isArrow, Member, Loc, Ty); + const CXXScopeSpec &SS, NamedDecl *Member, + SourceLocation Loc, QualType Ty, + const TemplateArgumentListInfo *TemplateArgs = 0) { + NestedNameSpecifier *Qualifier = 0; + SourceRange QualifierRange; + if (SS.isSet()) { + Qualifier = (NestedNameSpecifier *) SS.getScopeRep(); + QualifierRange = SS.getRange(); + } + + return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange, + Member, Loc, TemplateArgs, Ty); } -/// \brief Complete semantic analysis for a reference to the given declaration. -Sema::OwningExprResult -Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, - bool HasTrailingLParen, - const CXXScopeSpec *SS, - bool isAddressOfOperand) { - assert(D && "Cannot refer to a NULL declaration"); - DeclarationName Name = D->getDeclName(); +/// Return true if all the decls in the given result are instance +/// methods. +static bool IsOnlyInstanceMethods(const LookupResult &R) { + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + NamedDecl *D = (*I)->getUnderlyingDecl(); + + CXXMethodDecl *Method; + if (isa<FunctionTemplateDecl>(D)) + Method = cast<CXXMethodDecl>(cast<FunctionTemplateDecl>(D) + ->getTemplatedDecl()); + else if (isa<CXXMethodDecl>(D)) + Method = cast<CXXMethodDecl>(D); + else + return false; - // If this is an expression of the form &Class::member, don't build an - // implicit member ref, because we want a pointer to the member in general, - // not any specific instance's member. - if (isAddressOfOperand && SS && !SS->isEmpty() && !HasTrailingLParen) { - DeclContext *DC = computeDeclContext(*SS); - if (D && isa<CXXRecordDecl>(DC)) { - QualType DType; - if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { - DType = FD->getType().getNonReferenceType(); - } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { - DType = Method->getType(); - } else if (isa<OverloadedFunctionDecl>(D)) { - DType = Context.OverloadTy; - } - // Could be an inner type. That's diagnosed below, so ignore it here. - if (!DType.isNull()) { - // The pointer is type- and value-dependent if it points into something - // dependent. - bool Dependent = DC->isDependentContext(); - return BuildDeclRefExpr(D, DType, Loc, Dependent, Dependent, SS); - } - } + if (Method->isStatic()) + return false; } + return true; +} + +/// Builds an implicit member access expression from the given +/// unqualified lookup set, which is known to contain only class +/// members. +Sema::OwningExprResult +Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs) { + assert(!R.empty() && !R.isAmbiguous()); + + SourceLocation Loc = R.getNameLoc(); + // We may have found a field within an anonymous union or struct // (C++ [class.union]). // FIXME: This needs to happen post-isImplicitMemberReference? - if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) + // FIXME: template-ids inside anonymous structs? + if (FieldDecl *FD = R.getAsSingle<FieldDecl>()) if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion()) return BuildAnonymousStructUnionMemberReference(Loc, FD); - // Cope with an implicit member access in a C++ non-static member function. - QualType ThisType, MemberType; - if (isImplicitMemberReference(SS, D, Loc, ThisType, MemberType)) { + QualType ThisType; + if (isImplicitMemberReference(R, ThisType)) { Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType); - MarkDeclarationReferenced(Loc, D); - if (PerformObjectMemberConversion(This, D)) - return ExprError(); - - bool ShouldCheckUse = true; - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { - // Don't diagnose the use of a virtual member function unless it's - // explicitly qualified. - if (MD->isVirtual() && (!SS || !SS->isSet())) - ShouldCheckUse = false; - } - - if (ShouldCheckUse && DiagnoseUseOfDecl(D, Loc)) - return ExprError(); - return Owned(BuildMemberExpr(Context, This, true, SS, D, - Loc, MemberType)); + return BuildMemberReferenceExpr(ExprArg(*this, This), + /*OpLoc*/ SourceLocation(), + /*IsArrow*/ true, + SS, R, TemplateArgs); } - if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { + // Diagnose now if none of the available methods are static. + if (IsOnlyInstanceMethods(R)) + return ExprError(Diag(Loc, diag::err_member_call_without_object)); + + if (R.getAsSingle<FieldDecl>()) { if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) { - if (MD->isStatic()) + if (MD->isStatic()) { // "invalid use of member 'x' in static member function" - return ExprError(Diag(Loc,diag::err_invalid_member_use_in_static_method) - << FD->getDeclName()); + Diag(Loc, diag::err_invalid_member_use_in_static_method) + << R.getLookupName(); + return ExprError(); + } } // Any other ways we could have found the field in a well-formed // program would have been turned into implicit member expressions // above. - return ExprError(Diag(Loc, diag::err_invalid_non_static_member_use) - << FD->getDeclName()); - } - - if (isa<TypedefDecl>(D)) - return ExprError(Diag(Loc, diag::err_unexpected_typedef) << Name); - if (isa<ObjCInterfaceDecl>(D)) - return ExprError(Diag(Loc, diag::err_unexpected_interface) << Name); - if (isa<NamespaceDecl>(D)) - return ExprError(Diag(Loc, diag::err_unexpected_namespace) << Name); - - // Make the DeclRefExpr or BlockDeclRefExpr for the decl. - if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) - return BuildDeclRefExpr(Ovl, Context.OverloadTy, Loc, - false, false, SS); - else if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) - return BuildDeclRefExpr(Template, Context.OverloadTy, Loc, - false, false, SS); - else if (UnresolvedUsingValueDecl *UD = dyn_cast<UnresolvedUsingValueDecl>(D)) - return BuildDeclRefExpr(UD, Context.DependentTy, Loc, - /*TypeDependent=*/true, - /*ValueDependent=*/true, SS); + Diag(Loc, diag::err_invalid_non_static_member_use) + << R.getLookupName(); + return ExprError(); + } + + // We're not in an implicit member-reference context, but the lookup + // results might not require an instance. Try to build a non-member + // decl reference. + if (TemplateArgs) + return BuildTemplateIdExpr(SS, R, /* ADL */ false, *TemplateArgs); + + return BuildDeclarationNameExpr(SS, R, /*ADL*/ false); +} + +bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, + const LookupResult &R, + bool HasTrailingLParen) { + // Only when used directly as the postfix-expression of a call. + if (!HasTrailingLParen) + return false; + + // Never if a scope specifier was provided. + if (SS.isSet()) + return false; + + // Only in C++ or ObjC++. + if (!getLangOptions().CPlusPlus) + return false; + + // Turn off ADL when we find certain kinds of declarations during + // normal lookup: + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + NamedDecl *D = *I; + + // C++0x [basic.lookup.argdep]p3: + // -- a declaration of a class member + // Since using decls preserve this property, we check this on the + // original decl. + if (D->getDeclContext()->isRecord()) + return false; + + // C++0x [basic.lookup.argdep]p3: + // -- a block-scope function declaration that is not a + // using-declaration + // NOTE: we also trigger this for function templates (in fact, we + // don't check the decl type at all, since all other decl types + // turn off ADL anyway). + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + else if (D->getDeclContext()->isFunctionOrMethod()) + return false; + + // C++0x [basic.lookup.argdep]p3: + // -- a declaration that is neither a function or a function + // template + // And also for builtin functions. + if (isa<FunctionDecl>(D)) { + FunctionDecl *FDecl = cast<FunctionDecl>(D); + + // But also builtin functions. + if (FDecl->getBuiltinID() && FDecl->isImplicit()) + return false; + } else if (!isa<FunctionTemplateDecl>(D)) + return false; + } + + return true; +} + + +/// Diagnoses obvious problems with the use of the given declaration +/// as an expression. This is only actually called for lookups that +/// were not overloaded, and it doesn't promise that the declaration +/// will in fact be used. +static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) { + if (isa<TypedefDecl>(D)) { + S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName(); + return true; + } + + if (isa<ObjCInterfaceDecl>(D)) { + S.Diag(Loc, diag::err_unexpected_interface) << D->getDeclName(); + return true; + } + + if (isa<NamespaceDecl>(D)) { + S.Diag(Loc, diag::err_unexpected_namespace) << D->getDeclName(); + return true; + } + + return false; +} + +Sema::OwningExprResult +Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool NeedsADL) { + assert(R.getResultKind() != LookupResult::FoundUnresolvedValue); + + // If this isn't an overloaded result and we don't need ADL, just + // build an ordinary singleton decl ref. + if (!NeedsADL && !R.isOverloadedResult()) + return BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getFoundDecl()); + + // We only need to check the declaration if there's exactly one + // result, because in the overloaded case the results can only be + // functions and function templates. + if (R.isSingleResult() && + CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl())) + return ExprError(); + + bool Dependent + = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), 0); + UnresolvedLookupExpr *ULE + = UnresolvedLookupExpr::Create(Context, Dependent, + (NestedNameSpecifier*) SS.getScopeRep(), + SS.getRange(), + R.getLookupName(), R.getNameLoc(), + NeedsADL, R.isOverloadedResult()); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + ULE->addDecl(*I); + + return Owned(ULE); +} + + +/// \brief Complete semantic analysis for a reference to the given declaration. +Sema::OwningExprResult +Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, + SourceLocation Loc, NamedDecl *D) { + assert(D && "Cannot refer to a NULL declaration"); + assert(!isa<FunctionTemplateDecl>(D) && + "Cannot refer unambiguously to a function template"); + DeclarationName Name = D->getDeclName(); + + if (CheckDeclInExpr(*this, Loc, D)) + return ExprError(); ValueDecl *VD = cast<ValueDecl>(D); @@ -989,9 +1252,7 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, // this check when we're going to perform argument-dependent lookup // on this function name, because this might not be the function // that overload resolution actually selects. - bool ADL = getLangOptions().CPlusPlus && (!SS || !SS->isSet()) && - HasTrailingLParen; - if (!(ADL && isa<FunctionDecl>(VD)) && DiagnoseUseOfDecl(VD, Loc)) + if (DiagnoseUseOfDecl(VD, Loc)) return ExprError(); // Only create DeclRefExpr's for valid Decl's. @@ -1023,57 +1284,7 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, // If this reference is not in a block or if the referenced variable is // within the block, create a normal DeclRefExpr. - bool TypeDependent = false; - bool ValueDependent = false; - if (getLangOptions().CPlusPlus) { - // C++ [temp.dep.expr]p3: - // An id-expression is type-dependent if it contains: - // - an identifier that was declared with a dependent type, - if (VD->getType()->isDependentType()) - TypeDependent = true; - // - FIXME: a template-id that is dependent, - // - a conversion-function-id that specifies a dependent type, - else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName && - Name.getCXXNameType()->isDependentType()) - TypeDependent = true; - // - a nested-name-specifier that contains a class-name that - // names a dependent type. - else if (SS && !SS->isEmpty()) { - for (DeclContext *DC = computeDeclContext(*SS); - DC; DC = DC->getParent()) { - // FIXME: could stop early at namespace scope. - if (DC->isRecord()) { - CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); - if (Context.getTypeDeclType(Record)->isDependentType()) { - TypeDependent = true; - break; - } - } - } - } - - // C++ [temp.dep.constexpr]p2: - // - // An identifier is value-dependent if it is: - // - a name declared with a dependent type, - if (TypeDependent) - ValueDependent = true; - // - the name of a non-type template parameter, - else if (isa<NonTypeTemplateParmDecl>(VD)) - ValueDependent = true; - // - a constant with integral or enumeration type and is - // initialized with an expression that is value-dependent - else if (const VarDecl *Dcl = dyn_cast<VarDecl>(VD)) { - if (Context.getCanonicalType(Dcl->getType()).getCVRQualifiers() - == Qualifiers::Const && - Dcl->getInit()) { - ValueDependent = Dcl->getInit()->isValueDependent(); - } - } - } - - return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc, - TypeDependent, ValueDependent, SS); + return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc, &SS); } Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, @@ -1281,6 +1492,13 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType, if (exprType->isDependentType()) return false; + // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, + // the result is the size of the referenced type." + // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the + // result shall be the alignment of the referenced type." + if (const ReferenceType *Ref = exprType->getAs<ReferenceType>()) + exprType = Ref->getPointeeType(); + // C99 6.5.3.4p1: if (exprType->isFunctionType()) { // alignof(function) is allowed as an extension. @@ -1733,33 +1951,318 @@ static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy, return GDecl; } -Action::OwningExprResult -Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, - tok::TokenKind OpKind, SourceLocation MemberLoc, - DeclarationName MemberName, - bool HasExplicitTemplateArgs, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, - SourceLocation RAngleLoc, - DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS, - NamedDecl *FirstQualifierInScope) { - if (SS && SS->isInvalid()) +Sema::OwningExprResult +Sema::ActOnDependentMemberExpr(ExprArg Base, bool IsArrow, SourceLocation OpLoc, + const CXXScopeSpec &SS, + NamedDecl *FirstQualifierInScope, + DeclarationName Name, SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs) { + Expr *BaseExpr = Base.takeAs<Expr>(); + + // Even in dependent contexts, try to diagnose base expressions with + // obviously wrong types, e.g.: + // + // T* t; + // t.f; + // + // In Obj-C++, however, the above expression is valid, since it could be + // accessing the 'f' property if T is an Obj-C interface. The extra check + // allows this, while still reporting an error if T is a struct pointer. + if (!IsArrow) { + const PointerType *PT = BaseExpr->getType()->getAs<PointerType>(); + if (PT && (!getLangOptions().ObjC1 || + PT->getPointeeType()->isRecordType())) { + Diag(NameLoc, diag::err_typecheck_member_reference_struct_union) + << BaseExpr->getType() << BaseExpr->getSourceRange(); + return ExprError(); + } + } + + assert(BaseExpr->getType()->isDependentType()); + + // Get the type being accessed in BaseType. If this is an arrow, the BaseExpr + // must have pointer type, and the accessed type is the pointee. + return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, + IsArrow, OpLoc, + static_cast<NestedNameSpecifier*>(SS.getScopeRep()), + SS.getRange(), + FirstQualifierInScope, + Name, NameLoc, + TemplateArgs)); +} + +/// We know that the given qualified member reference points only to +/// declarations which do not belong to the static type of the base +/// expression. Diagnose the problem. +static void DiagnoseQualifiedMemberReference(Sema &SemaRef, + Expr *BaseExpr, + QualType BaseType, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + const LookupResult &R) { + DeclContext *DC = R.getRepresentativeDecl()->getDeclContext(); + + // FIXME: this is an exceedingly lame diagnostic for some of the more + // complicated cases here. + SemaRef.Diag(R.getNameLoc(), diag::err_not_direct_base_or_virtual) + << QualifierRange << DC << BaseType; +} + +// Check whether the declarations we found through a nested-name +// specifier in a member expression are actually members of the base +// type. The restriction here is: +// +// C++ [expr.ref]p2: +// ... In these cases, the id-expression shall name a +// member of the class or of one of its base classes. +// +// So it's perfectly legitimate for the nested-name specifier to name +// an unrelated class, and for us to find an overload set including +// decls from classes which are not superclasses, as long as the decl +// we actually pick through overload resolution is from a superclass. +bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, + QualType BaseType, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + const LookupResult &R) { + QualType BaseTypeCanon + = Context.getCanonicalType(BaseType).getUnqualifiedType(); + + bool FoundValid = false; + + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + TypeDecl* TyD = cast<TypeDecl>((*I)->getUnderlyingDecl()->getDeclContext()); + CanQualType MemberTypeCanon + = Context.getCanonicalType(Context.getTypeDeclType(TyD)); + + if (BaseTypeCanon == MemberTypeCanon || + IsDerivedFrom(BaseTypeCanon, MemberTypeCanon)) { + FoundValid = true; + break; + } + } + + if (!FoundValid) { + DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, + Qualifier, QualifierRange, R); + return true; + } + + return false; +} + +Sema::OwningExprResult +Sema::BuildMemberReferenceExpr(ExprArg BaseArg, + SourceLocation OpLoc, bool IsArrow, + const CXXScopeSpec &SS, + NamedDecl *FirstQualifierInScope, + DeclarationName Name, SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs) { + Expr *Base = BaseArg.takeAs<Expr>(); + + if (Base->getType()->isDependentType()) + return ActOnDependentMemberExpr(ExprArg(*this, Base), + IsArrow, OpLoc, + SS, FirstQualifierInScope, + Name, NameLoc, + TemplateArgs); + + LookupResult R(*this, Name, NameLoc, LookupMemberName); + OwningExprResult Result = + LookupMemberExpr(R, Base, IsArrow, OpLoc, + SS, FirstQualifierInScope, + /*ObjCImpDecl*/ DeclPtrTy()); + + if (Result.isInvalid()) { + Owned(Base); return ExprError(); + } - // Since this might be a postfix expression, get rid of ParenListExprs. - Base = MaybeConvertParenListExprToParenExpr(S, move(Base)); + if (Result.get()) + return move(Result); + + return BuildMemberReferenceExpr(ExprArg(*this, Base), OpLoc, + IsArrow, SS, R, TemplateArgs); +} +Sema::OwningExprResult +Sema::BuildMemberReferenceExpr(ExprArg Base, SourceLocation OpLoc, + bool IsArrow, const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs) { Expr *BaseExpr = Base.takeAs<Expr>(); + QualType BaseType = BaseExpr->getType(); + if (IsArrow) { + assert(BaseType->isPointerType()); + BaseType = BaseType->getAs<PointerType>()->getPointeeType(); + } + + NestedNameSpecifier *Qualifier = + static_cast<NestedNameSpecifier*>(SS.getScopeRep()); + DeclarationName MemberName = R.getLookupName(); + SourceLocation MemberLoc = R.getNameLoc(); + + if (R.isAmbiguous()) + return ExprError(); + + if (R.empty()) { + // Rederive where we looked up. + DeclContext *DC = (SS.isSet() + ? computeDeclContext(SS, false) + : BaseType->getAs<RecordType>()->getDecl()); + + Diag(R.getNameLoc(), diag::err_no_member) + << MemberName << DC << BaseExpr->getSourceRange(); + return ExprError(); + } + + // We can't always diagnose the problem yet: it's permitted for + // lookup to find things from an invalid context as long as they + // don't get picked by overload resolution. + if (SS.isSet() && CheckQualifiedMemberReference(BaseExpr, BaseType, + Qualifier, SS.getRange(), R)) + return ExprError(); + + // Construct an unresolved result if we in fact got an unresolved + // result. + if (R.isOverloadedResult() || R.isUnresolvableResult()) { + bool Dependent = R.isUnresolvableResult(); + Dependent = Dependent || + UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), + TemplateArgs); + + UnresolvedMemberExpr *MemExpr + = UnresolvedMemberExpr::Create(Context, Dependent, + R.isUnresolvableResult(), + BaseExpr, IsArrow, OpLoc, + Qualifier, SS.getRange(), + MemberName, MemberLoc, + TemplateArgs); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + MemExpr->addDecl(*I); + + return Owned(MemExpr); + } + + assert(R.isSingleResult()); + NamedDecl *MemberDecl = R.getFoundDecl(); + + // FIXME: diagnose the presence of template arguments now. + + // If the decl being referenced had an error, return an error for this + // sub-expr without emitting another error, in order to avoid cascading + // error cases. + if (MemberDecl->isInvalidDecl()) + return ExprError(); + + bool ShouldCheckUse = true; + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) { + // Don't diagnose the use of a virtual member function unless it's + // explicitly qualified. + if (MD->isVirtual() && !SS.isSet()) + ShouldCheckUse = false; + } + + // Check the use of this member. + if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) { + Owned(BaseExpr); + return ExprError(); + } + + if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) { + // We may have found a field within an anonymous union or struct + // (C++ [class.union]). + if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion()) + return BuildAnonymousStructUnionMemberReference(MemberLoc, FD, + BaseExpr, OpLoc); + + // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref] + QualType MemberType = FD->getType(); + if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) + MemberType = Ref->getPointeeType(); + else { + Qualifiers BaseQuals = BaseType.getQualifiers(); + BaseQuals.removeObjCGCAttr(); + if (FD->isMutable()) BaseQuals.removeConst(); + + Qualifiers MemberQuals + = Context.getCanonicalType(MemberType).getQualifiers(); + + Qualifiers Combined = BaseQuals + MemberQuals; + if (Combined != MemberQuals) + MemberType = Context.getQualifiedType(MemberType, Combined); + } + + MarkDeclarationReferenced(MemberLoc, FD); + if (PerformObjectMemberConversion(BaseExpr, FD)) + return ExprError(); + return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, + FD, MemberLoc, MemberType)); + } + + if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { + MarkDeclarationReferenced(MemberLoc, Var); + return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, + Var, MemberLoc, + Var->getType().getNonReferenceType())); + } + + if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) { + MarkDeclarationReferenced(MemberLoc, MemberDecl); + return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, + MemberFn, MemberLoc, + MemberFn->getType())); + } + + if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { + MarkDeclarationReferenced(MemberLoc, MemberDecl); + return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, + Enum, MemberLoc, Enum->getType())); + } + + Owned(BaseExpr); + + if (isa<TypeDecl>(MemberDecl)) + return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type) + << MemberName << int(IsArrow)); + + // We found a declaration kind that we didn't expect. This is a + // generic error message that tells the user that she can't refer + // to this member with '.' or '->'. + return ExprError(Diag(MemberLoc, + diag::err_typecheck_member_reference_unknown) + << MemberName << int(IsArrow)); +} + +/// Look up the given member of the given non-type-dependent +/// expression. This can return in one of two ways: +/// * If it returns a sentinel null-but-valid result, the caller will +/// assume that lookup was performed and the results written into +/// the provided structure. It will take over from there. +/// * Otherwise, the returned expression will be produced in place of +/// an ordinary member expression. +/// +/// The ObjCImpDecl bit is a gross hack that will need to be properly +/// fixed for ObjC++. +Sema::OwningExprResult +Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, + bool IsArrow, SourceLocation OpLoc, + const CXXScopeSpec &SS, + NamedDecl *FirstQualifierInScope, + DeclPtrTy ObjCImpDecl) { assert(BaseExpr && "no base expression"); // Perform default conversions. DefaultFunctionArrayConversion(BaseExpr); QualType BaseType = BaseExpr->getType(); + assert(!BaseType->isDependentType()); + + DeclarationName MemberName = R.getLookupName(); + SourceLocation MemberLoc = R.getNameLoc(); // If the user is trying to apply -> or . to a function pointer - // type, it's probably because the forgot parentheses to call that + // type, it's probably because they forgot parentheses to call that // function. Suggest the addition of those parentheses, build the // call, and continue on. if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { @@ -1767,8 +2270,8 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, = Ptr->getPointeeType()->getAs<FunctionProtoType>()) { QualType ResultTy = Fun->getResultType(); if (Fun->getNumArgs() == 0 && - ((OpKind == tok::period && ResultTy->isRecordType()) || - (OpKind == tok::arrow && ResultTy->isPointerType() && + ((!IsArrow && ResultTy->isRecordType()) || + (IsArrow && ResultTy->isPointerType() && ResultTy->getAs<PointerType>()->getPointeeType() ->isRecordType()))) { SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd()); @@ -1777,10 +2280,10 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, << CodeModificationHint::CreateInsertion(Loc, "()"); OwningExprResult NewBase - = ActOnCallExpr(S, ExprArg(*this, BaseExpr), Loc, + = ActOnCallExpr(0, ExprArg(*this, BaseExpr), Loc, MultiExprArg(*this, 0, 0), 0, Loc); if (NewBase.isInvalid()) - return move(NewBase); + return ExprError(); BaseExpr = NewBase.takeAs<Expr>(); DefaultFunctionArrayConversion(BaseExpr); @@ -1799,10 +2302,22 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast); } } + + // If this is an Objective-C pseudo-builtin and a definition is provided then + // use that. + if (Context.isObjCSelType(BaseType)) { + // We have an 'SEL' type. Rather than fall through, we check if this + // is a reference to 'sel_id'. + if (BaseType != Context.ObjCSelRedefinitionType) { + BaseType = Context.ObjCSelRedefinitionType; + ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast); + } + } + assert(!BaseType.isNull() && "no type for member expression"); // Handle properties on ObjC 'Class' types. - if (OpKind == tok::period && BaseType->isObjCClassType()) { + if (!IsArrow && BaseType->isObjCClassType()) { // Also must look for a getter name which uses property syntax. IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); Selector Sel = PP.getSelectorTable().getNullarySelector(Member); @@ -1856,76 +2371,21 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, BaseType = Context.ObjCClassRedefinitionType; ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast); } - - // Get the type being accessed in BaseType. If this is an arrow, the BaseExpr - // must have pointer type, and the accessed type is the pointee. - if (OpKind == tok::arrow) { - if (BaseType->isDependentType()) { - NestedNameSpecifier *Qualifier = 0; - if (SS) { - Qualifier = static_cast<NestedNameSpecifier *>(SS->getScopeRep()); - if (!FirstQualifierInScope) - FirstQualifierInScope = FindFirstQualifierInScope(S, Qualifier); - } - return Owned(CXXUnresolvedMemberExpr::Create(Context, BaseExpr, true, - OpLoc, Qualifier, - SS? SS->getRange() : SourceRange(), - FirstQualifierInScope, - MemberName, - MemberLoc, - HasExplicitTemplateArgs, - LAngleLoc, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, - RAngleLoc)); - } - else if (const PointerType *PT = BaseType->getAs<PointerType>()) + if (IsArrow) { + if (const PointerType *PT = BaseType->getAs<PointerType>()) BaseType = PT->getPointeeType(); else if (BaseType->isObjCObjectPointerType()) ; - else - return ExprError(Diag(MemberLoc, - diag::err_typecheck_member_reference_arrow) - << BaseType << BaseExpr->getSourceRange()); - } else if (BaseType->isDependentType()) { - // Require that the base type isn't a pointer type - // (so we'll report an error for) - // T* t; - // t.f; - // - // In Obj-C++, however, the above expression is valid, since it could be - // accessing the 'f' property if T is an Obj-C interface. The extra check - // allows this, while still reporting an error if T is a struct pointer. - const PointerType *PT = BaseType->getAs<PointerType>(); - - if (!PT || (getLangOptions().ObjC1 && - !PT->getPointeeType()->isRecordType())) { - NestedNameSpecifier *Qualifier = 0; - if (SS) { - Qualifier = static_cast<NestedNameSpecifier *>(SS->getScopeRep()); - if (!FirstQualifierInScope) - FirstQualifierInScope = FindFirstQualifierInScope(S, Qualifier); - } - - return Owned(CXXUnresolvedMemberExpr::Create(Context, - BaseExpr, false, - OpLoc, - Qualifier, - SS? SS->getRange() : SourceRange(), - FirstQualifierInScope, - MemberName, - MemberLoc, - HasExplicitTemplateArgs, - LAngleLoc, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, - RAngleLoc)); - } + else { + Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) + << BaseType << BaseExpr->getSourceRange(); + return ExprError(); } + } - // Handle field access to simple records. This also handles access to fields - // of the ObjC 'id' struct. + // Handle field access to simple records. This also handles access + // to fields of the ObjC 'id' struct. if (const RecordType *RTy = BaseType->getAs<RecordType>()) { RecordDecl *RDecl = RTy->getDecl(); if (RequireCompleteType(OpLoc, BaseType, @@ -1934,155 +2394,25 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, return ExprError(); DeclContext *DC = RDecl; - if (SS && SS->isSet()) { + if (SS.isSet()) { // If the member name was a qualified-id, look into the // nested-name-specifier. - DC = computeDeclContext(*SS, false); + DC = computeDeclContext(SS, false); if (!isa<TypeDecl>(DC)) { Diag(MemberLoc, diag::err_qualified_member_nonclass) - << DC << SS->getRange(); + << DC << SS.getRange(); return ExprError(); } // FIXME: If DC is not computable, we should build a - // CXXUnresolvedMemberExpr. + // CXXDependentScopeMemberExpr. assert(DC && "Cannot handle non-computable dependent contexts in lookup"); } // The record definition is complete, now make sure the member is valid. - LookupResult Result(*this, MemberName, MemberLoc, LookupMemberName); - LookupQualifiedName(Result, DC); - - if (Result.empty()) - return ExprError(Diag(MemberLoc, diag::err_no_member) - << MemberName << DC << BaseExpr->getSourceRange()); - if (Result.isAmbiguous()) - return ExprError(); - - NamedDecl *MemberDecl = Result.getAsSingleDecl(Context); - - if (SS && SS->isSet()) { - TypeDecl* TyD = cast<TypeDecl>(MemberDecl->getDeclContext()); - QualType BaseTypeCanon - = Context.getCanonicalType(BaseType).getUnqualifiedType(); - QualType MemberTypeCanon - = Context.getCanonicalType(Context.getTypeDeclType(TyD)); - - if (BaseTypeCanon != MemberTypeCanon && - !IsDerivedFrom(BaseTypeCanon, MemberTypeCanon)) - return ExprError(Diag(SS->getBeginLoc(), - diag::err_not_direct_base_or_virtual) - << MemberTypeCanon << BaseTypeCanon); - } - - // If the decl being referenced had an error, return an error for this - // sub-expr without emitting another error, in order to avoid cascading - // error cases. - if (MemberDecl->isInvalidDecl()) - return ExprError(); - - bool ShouldCheckUse = true; - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) { - // Don't diagnose the use of a virtual member function unless it's - // explicitly qualified. - if (MD->isVirtual() && (!SS || !SS->isSet())) - ShouldCheckUse = false; - } - - // Check the use of this field - if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) - return ExprError(); - - if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) { - // We may have found a field within an anonymous union or struct - // (C++ [class.union]). - if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion()) - return BuildAnonymousStructUnionMemberReference(MemberLoc, FD, - BaseExpr, OpLoc); - - // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref] - QualType MemberType = FD->getType(); - if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) - MemberType = Ref->getPointeeType(); - else { - Qualifiers BaseQuals = BaseType.getQualifiers(); - BaseQuals.removeObjCGCAttr(); - if (FD->isMutable()) BaseQuals.removeConst(); - - Qualifiers MemberQuals - = Context.getCanonicalType(MemberType).getQualifiers(); - - Qualifiers Combined = BaseQuals + MemberQuals; - if (Combined != MemberQuals) - MemberType = Context.getQualifiedType(MemberType, Combined); - } - - MarkDeclarationReferenced(MemberLoc, FD); - if (PerformObjectMemberConversion(BaseExpr, FD)) - return ExprError(); - return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, - FD, MemberLoc, MemberType)); - } - - if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { - MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, - Var, MemberLoc, - Var->getType().getNonReferenceType())); - } - if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) { - MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, - MemberFn, MemberLoc, - MemberFn->getType())); - } - if (FunctionTemplateDecl *FunTmpl - = dyn_cast<FunctionTemplateDecl>(MemberDecl)) { - MarkDeclarationReferenced(MemberLoc, MemberDecl); - - if (HasExplicitTemplateArgs) - return Owned(MemberExpr::Create(Context, BaseExpr, OpKind == tok::arrow, - (NestedNameSpecifier *)(SS? SS->getScopeRep() : 0), - SS? SS->getRange() : SourceRange(), - FunTmpl, MemberLoc, true, - LAngleLoc, ExplicitTemplateArgs, - NumExplicitTemplateArgs, RAngleLoc, - Context.OverloadTy)); - - return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, - FunTmpl, MemberLoc, - Context.OverloadTy)); - } - if (OverloadedFunctionDecl *Ovl - = dyn_cast<OverloadedFunctionDecl>(MemberDecl)) { - if (HasExplicitTemplateArgs) - return Owned(MemberExpr::Create(Context, BaseExpr, OpKind == tok::arrow, - (NestedNameSpecifier *)(SS? SS->getScopeRep() : 0), - SS? SS->getRange() : SourceRange(), - Ovl, MemberLoc, true, - LAngleLoc, ExplicitTemplateArgs, - NumExplicitTemplateArgs, RAngleLoc, - Context.OverloadTy)); - - return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, - Ovl, MemberLoc, Context.OverloadTy)); - } - if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { - MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(BuildMemberExpr(Context, BaseExpr, OpKind == tok::arrow, SS, - Enum, MemberLoc, Enum->getType())); - } - if (isa<TypeDecl>(MemberDecl)) - return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type) - << MemberName << int(OpKind == tok::arrow)); - - // We found a declaration kind that we didn't expect. This is a - // generic error message that tells the user that she can't refer - // to this member with '.' or '->'. - return ExprError(Diag(MemberLoc, - diag::err_typecheck_member_reference_unknown) - << MemberName << int(OpKind == tok::arrow)); + LookupQualifiedName(R, DC); + return Owned((Expr*) 0); } // Handle pseudo-destructors (C++ [expr.pseudo]). Since anything referring @@ -2118,18 +2448,17 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // FIXME: We've lost the precise spelling of the type by going through // DeclarationName. Can we do better? return Owned(new (Context) CXXPseudoDestructorExpr(Context, BaseExpr, - OpKind == tok::arrow, - OpLoc, - (NestedNameSpecifier *)(SS? SS->getScopeRep() : 0), - SS? SS->getRange() : SourceRange(), + IsArrow, OpLoc, + (NestedNameSpecifier *) SS.getScopeRep(), + SS.getRange(), MemberName.getCXXNameType(), MemberLoc)); } // Handle access to Objective-C instance variables, such as "Obj->ivar" and // (*Obj).ivar. - if ((OpKind == tok::arrow && BaseType->isObjCObjectPointerType()) || - (OpKind == tok::period && BaseType->isObjCInterfaceType())) { + if ((IsArrow && BaseType->isObjCObjectPointerType()) || + (!IsArrow && BaseType->isObjCInterfaceType())) { const ObjCObjectPointerType *OPT = BaseType->getAs<ObjCObjectPointerType>(); const ObjCInterfaceType *IFaceT = OPT ? OPT->getInterfaceType() : BaseType->getAs<ObjCInterfaceType>(); @@ -2184,7 +2513,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), MemberLoc, BaseExpr, - OpKind == tok::arrow)); + IsArrow)); } return ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) << IDecl->getDeclName() << MemberName @@ -2192,8 +2521,8 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, } } // Handle properties on 'id' and qualified "id". - if (OpKind == tok::period && (BaseType->isObjCIdType() || - BaseType->isObjCQualifiedIdType())) { + if (!IsArrow && (BaseType->isObjCIdType() || + BaseType->isObjCQualifiedIdType())) { const ObjCObjectPointerType *QIdTy = BaseType->getAs<ObjCObjectPointerType>(); IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); @@ -2226,8 +2555,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // Handle Objective-C property access, which is "Obj.property" where Obj is a // pointer to a (potentially qualified) interface type. const ObjCObjectPointerType *OPT; - if (OpKind == tok::period && - (OPT = BaseType->getAsObjCInterfacePointerType())) { + if (!IsArrow && (OPT = BaseType->getAsObjCInterfacePointerType())) { const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); ObjCInterfaceDecl *IFace = IFaceT->getDecl(); IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); @@ -2312,7 +2640,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, } // Handle the following exceptional case (*Obj).isa. - if (OpKind == tok::period && + if (!IsArrow && BaseType->isSpecificBuiltinType(BuiltinType::ObjCId) && MemberName.getAsIdentifierInfo()->isStr("isa")) return Owned(new (Context) ObjCIsaExpr(BaseExpr, false, MemberLoc, @@ -2334,75 +2662,105 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, return ExprError(); } -Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg Base, +static Sema::OwningExprResult DiagnoseDtorReference(Sema &SemaRef, + SourceLocation NameLoc, + Sema::ExprArg MemExpr) { + Expr *E = (Expr *) MemExpr.get(); + SourceLocation ExpectedLParenLoc = SemaRef.PP.getLocForEndOfToken(NameLoc); + SemaRef.Diag(E->getLocStart(), diag::err_dtor_expr_without_call) + << isa<CXXPseudoDestructorExpr>(E) + << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()"); + + return SemaRef.ActOnCallExpr(/*Scope*/ 0, + move(MemExpr), + /*LPLoc*/ ExpectedLParenLoc, + Sema::MultiExprArg(SemaRef, 0, 0), + /*CommaLocs*/ 0, + /*RPLoc*/ ExpectedLParenLoc); +} + +/// The main callback when the parser finds something like +/// expression . [nested-name-specifier] identifier +/// expression -> [nested-name-specifier] identifier +/// where 'identifier' encompasses a fairly broad spectrum of +/// possibilities, including destructor and operator references. +/// +/// \param OpKind either tok::arrow or tok::period +/// \param HasTrailingLParen whether the next token is '(', which +/// is used to diagnose mis-uses of special members that can +/// only be called +/// \param ObjCImpDecl the current ObjC @implementation decl; +/// this is an ugly hack around the fact that ObjC @implementations +/// aren't properly put in the context chain +Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg, SourceLocation OpLoc, tok::TokenKind OpKind, const CXXScopeSpec &SS, - UnqualifiedId &Member, + UnqualifiedId &Id, DeclPtrTy ObjCImpDecl, bool HasTrailingLParen) { - if (Member.getKind() == UnqualifiedId::IK_TemplateId) { - TemplateName Template - = TemplateName::getFromVoidPointer(Member.TemplateId->Template); - - // FIXME: We're going to end up looking up the template based on its name, - // twice! - DeclarationName Name; - if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl()) - Name = ActualTemplate->getDeclName(); - else if (OverloadedFunctionDecl *Ovl = Template.getAsOverloadedFunctionDecl()) - Name = Ovl->getDeclName(); - else { - DependentTemplateName *DTN = Template.getAsDependentTemplateName(); - if (DTN->isIdentifier()) - Name = DTN->getIdentifier(); - else - Name = Context.DeclarationNames.getCXXOperatorName(DTN->getOperator()); + if (SS.isSet() && SS.isInvalid()) + return ExprError(); + + TemplateArgumentListInfo TemplateArgsBuffer; + + // Decompose the name into its component parts. + DeclarationName Name; + SourceLocation NameLoc; + const TemplateArgumentListInfo *TemplateArgs; + DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer, + Name, NameLoc, TemplateArgs); + + bool IsArrow = (OpKind == tok::arrow); + + NamedDecl *FirstQualifierInScope + = (!SS.isSet() ? 0 : FindFirstQualifierInScope(S, + static_cast<NestedNameSpecifier*>(SS.getScopeRep()))); + + // This is a postfix expression, so get rid of ParenListExprs. + BaseArg = MaybeConvertParenListExprToParenExpr(S, move(BaseArg)); + + Expr *Base = BaseArg.takeAs<Expr>(); + OwningExprResult Result(*this); + if (Base->getType()->isDependentType()) { + Result = ActOnDependentMemberExpr(ExprArg(*this, Base), + IsArrow, OpLoc, + SS, FirstQualifierInScope, + Name, NameLoc, + TemplateArgs); + } else { + LookupResult R(*this, Name, NameLoc, LookupMemberName); + if (TemplateArgs) { + // Re-use the lookup done for the template name. + DecomposeTemplateName(R, Id); + } else { + Result = LookupMemberExpr(R, Base, IsArrow, OpLoc, + SS, FirstQualifierInScope, + ObjCImpDecl); + + if (Result.isInvalid()) { + Owned(Base); + return ExprError(); + } + + if (Result.get()) { + // The only way a reference to a destructor can be used is to + // immediately call it, which falls into this case. If the + // next token is not a '(', produce a diagnostic and build the + // call now. + if (!HasTrailingLParen && + Id.getKind() == UnqualifiedId::IK_DestructorName) + return DiagnoseDtorReference(*this, NameLoc, move(Result)); + + return move(Result); + } } - - // Translate the parser's template argument list in our AST format. - ASTTemplateArgsPtr TemplateArgsPtr(*this, - Member.TemplateId->getTemplateArgs(), - Member.TemplateId->NumArgs); - - llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; - translateTemplateArguments(TemplateArgsPtr, - TemplateArgs); - TemplateArgsPtr.release(); - - // Do we have the save the actual template name? We might need it... - return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, - Member.TemplateId->TemplateNameLoc, - Name, true, Member.TemplateId->LAngleLoc, - TemplateArgs.data(), TemplateArgs.size(), - Member.TemplateId->RAngleLoc, DeclPtrTy(), - &SS); + + Result = BuildMemberReferenceExpr(ExprArg(*this, Base), OpLoc, + IsArrow, SS, R, TemplateArgs); } - - // FIXME: We lose a lot of source information by mapping directly to the - // DeclarationName. - OwningExprResult Result - = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, - Member.getSourceRange().getBegin(), - GetNameFromUnqualifiedId(Member), - ObjCImpDecl, &SS); - - if (Result.isInvalid() || HasTrailingLParen || - Member.getKind() != UnqualifiedId::IK_DestructorName) - return move(Result); - - // The only way a reference to a destructor can be used is to - // immediately call them. Since the next token is not a '(', produce a - // diagnostic and build the call now. - Expr *E = (Expr *)Result.get(); - SourceLocation ExpectedLParenLoc - = PP.getLocForEndOfToken(Member.getSourceRange().getEnd()); - Diag(E->getLocStart(), diag::err_dtor_expr_without_call) - << isa<CXXPseudoDestructorExpr>(E) - << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()"); - - return ActOnCallExpr(0, move(Result), ExpectedLParenLoc, - MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc); + + return move(Result); } Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, @@ -2468,17 +2826,14 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by // assignment, to the types of the corresponding parameter, ... unsigned NumArgsInProto = Proto->getNumArgs(); - unsigned NumArgsToCheck = NumArgs; bool Invalid = false; - + // If too few arguments are available (and we don't have default // arguments for the remaining parameters), don't make the call. if (NumArgs < NumArgsInProto) { if (!FDecl || NumArgs < FDecl->getMinRequiredArguments()) return Diag(RParenLoc, diag::err_typecheck_call_too_few_args) << Fn->getType()->isBlockPointerType() << Fn->getSourceRange(); - // Use default arguments for missing arguments - NumArgsToCheck = NumArgsInProto; Call->setNumArgs(Context, NumArgsInProto); } @@ -2493,25 +2848,55 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, Args[NumArgs-1]->getLocEnd()); // This deletes the extra arguments. Call->setNumArgs(Context, NumArgsInProto); - Invalid = true; + return true; } - NumArgsToCheck = NumArgsInProto; } + llvm::SmallVector<Expr *, 8> AllArgs; + VariadicCallType CallType = + Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply; + if (Fn->getType()->isBlockPointerType()) + CallType = VariadicBlock; // Block + else if (isa<MemberExpr>(Fn)) + CallType = VariadicMethod; + Invalid = GatherArgumentsForCall(Call->getSourceRange().getBegin(), FDecl, + Proto, 0, Args, NumArgs, AllArgs, CallType); + if (Invalid) + return true; + unsigned TotalNumArgs = AllArgs.size(); + for (unsigned i = 0; i < TotalNumArgs; ++i) + Call->setArg(i, AllArgs[i]); + + return false; +} +bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, + FunctionDecl *FDecl, + const FunctionProtoType *Proto, + unsigned FirstProtoArg, + Expr **Args, unsigned NumArgs, + llvm::SmallVector<Expr *, 8> &AllArgs, + VariadicCallType CallType) { + unsigned NumArgsInProto = Proto->getNumArgs(); + unsigned NumArgsToCheck = NumArgs; + bool Invalid = false; + if (NumArgs != NumArgsInProto) + // Use default arguments for missing arguments + NumArgsToCheck = NumArgsInProto; + unsigned ArgIx = 0; // Continue to check argument types (even if we have too few/many args). - for (unsigned i = 0; i != NumArgsToCheck; i++) { + for (unsigned i = FirstProtoArg; i != NumArgsToCheck; i++) { QualType ProtoArgType = Proto->getArgType(i); - + Expr *Arg; - if (i < NumArgs) { - Arg = Args[i]; - + if (ArgIx < NumArgs) { + Arg = Args[ArgIx++]; + if (RequireCompleteType(Arg->getSourceRange().getBegin(), ProtoArgType, PDiag(diag::err_call_incomplete_argument) - << Arg->getSourceRange())) + << Arg->getSourceRange())) return true; - + // Pass the argument. if (PerformCopyInitialization(Arg, ProtoArgType, "passing")) return true; @@ -2520,35 +2905,26 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, Arg = MaybeBindToTemporary(Arg).takeAs<Expr>(); } else { ParmVarDecl *Param = FDecl->getParamDecl(i); - + OwningExprResult ArgExpr = - BuildCXXDefaultArgExpr(Call->getSourceRange().getBegin(), - FDecl, Param); + BuildCXXDefaultArgExpr(CallLoc, FDecl, Param); if (ArgExpr.isInvalid()) return true; - + Arg = ArgExpr.takeAs<Expr>(); } - - Call->setArg(i, Arg); + AllArgs.push_back(Arg); } - + // If this is a variadic call, handle args passed through "...". - if (Proto->isVariadic()) { - VariadicCallType CallType = VariadicFunction; - if (Fn->getType()->isBlockPointerType()) - CallType = VariadicBlock; // Block - else if (isa<MemberExpr>(Fn)) - CallType = VariadicMethod; - + if (CallType != VariadicDoesNotApply) { // Promote the arguments (C99 6.5.2.2p7). - for (unsigned i = NumArgsInProto; i < NumArgs; i++) { + for (unsigned i = ArgIx; i < NumArgs; i++) { Expr *Arg = Args[i]; Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType); - Call->setArg(i, Arg); + AllArgs.push_back(Arg); } } - return Invalid; } @@ -2557,22 +2933,22 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, /// whether argument-dependent lookup is available, whether it has explicit /// template arguments, etc. void Sema::DeconstructCallFunction(Expr *FnExpr, - NamedDecl *&Function, + llvm::SmallVectorImpl<NamedDecl*> &Fns, DeclarationName &Name, NestedNameSpecifier *&Qualifier, SourceRange &QualifierRange, bool &ArgumentDependentLookup, + bool &Overloaded, bool &HasExplicitTemplateArguments, - const TemplateArgumentLoc *&ExplicitTemplateArgs, - unsigned &NumExplicitTemplateArgs) { + TemplateArgumentListInfo &ExplicitTemplateArgs) { // Set defaults for all of the output parameters. - Function = 0; Name = DeclarationName(); Qualifier = 0; QualifierRange = SourceRange(); - ArgumentDependentLookup = getLangOptions().CPlusPlus; + ArgumentDependentLookup = false; + Overloaded = false; HasExplicitTemplateArguments = false; - + // If we're directly calling a function, get the appropriate declaration. // Also, in C++, keep track of whether we should perform argument-dependent // lookup and whether there were any explicitly-specified template arguments. @@ -2580,59 +2956,31 @@ void Sema::DeconstructCallFunction(Expr *FnExpr, if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr)) FnExpr = IcExpr->getSubExpr(); else if (ParenExpr *PExpr = dyn_cast<ParenExpr>(FnExpr)) { - // Parentheses around a function disable ADL - // (C++0x [basic.lookup.argdep]p1). - ArgumentDependentLookup = false; FnExpr = PExpr->getSubExpr(); } else if (isa<UnaryOperator>(FnExpr) && cast<UnaryOperator>(FnExpr)->getOpcode() == UnaryOperator::AddrOf) { FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr(); } else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) { - Function = dyn_cast<NamedDecl>(DRExpr->getDecl()); - if ((Qualifier = DRExpr->getQualifier())) { - ArgumentDependentLookup = false; + Fns.push_back(cast<NamedDecl>(DRExpr->getDecl())); + ArgumentDependentLookup = false; + if ((Qualifier = DRExpr->getQualifier())) QualifierRange = DRExpr->getQualifierRange(); - } break; - } else if (UnresolvedFunctionNameExpr *DepName - = dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) { - Name = DepName->getName(); - break; - } else if (TemplateIdRefExpr *TemplateIdRef - = dyn_cast<TemplateIdRefExpr>(FnExpr)) { - Function = TemplateIdRef->getTemplateName().getAsTemplateDecl(); - if (!Function) - Function = TemplateIdRef->getTemplateName().getAsOverloadedFunctionDecl(); - HasExplicitTemplateArguments = true; - ExplicitTemplateArgs = TemplateIdRef->getTemplateArgs(); - NumExplicitTemplateArgs = TemplateIdRef->getNumTemplateArgs(); - - // C++ [temp.arg.explicit]p6: - // [Note: For simple function names, argument dependent lookup (3.4.2) - // applies even when the function name is not visible within the - // scope of the call. This is because the call still has the syntactic - // form of a function call (3.4.1). But when a function template with - // explicit template arguments is used, the call does not have the - // correct syntactic form unless there is a function template with - // that name visible at the point of the call. If no such name is - // visible, the call is not syntactically well-formed and - // argument-dependent lookup does not apply. If some such name is - // visible, argument dependent lookup applies and additional function - // templates may be found in other namespaces. - // - // The summary of this paragraph is that, if we get to this point and the - // template-id was not a qualified name, then argument-dependent lookup - // is still possible. - if ((Qualifier = TemplateIdRef->getQualifier())) { - ArgumentDependentLookup = false; - QualifierRange = TemplateIdRef->getQualifierRange(); + } else if (UnresolvedLookupExpr *UnresLookup + = dyn_cast<UnresolvedLookupExpr>(FnExpr)) { + Name = UnresLookup->getName(); + Fns.append(UnresLookup->decls_begin(), UnresLookup->decls_end()); + ArgumentDependentLookup = UnresLookup->requiresADL(); + Overloaded = UnresLookup->isOverloaded(); + if ((Qualifier = UnresLookup->getQualifier())) + QualifierRange = UnresLookup->getQualifierRange(); + if (UnresLookup->hasExplicitTemplateArgs()) { + HasExplicitTemplateArguments = true; + UnresLookup->copyTemplateArgumentsInto(ExplicitTemplateArgs); } break; } else { - // Any kind of name that does not refer to a declaration (or - // set of declarations) disables ADL (C++0x [basic.lookup.argdep]p3). - ArgumentDependentLookup = false; break; } } @@ -2653,9 +3001,6 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, Expr *Fn = fn.takeAs<Expr>(); Expr **Args = reinterpret_cast<Expr**>(args.release()); assert(Fn && "no function call expression"); - FunctionDecl *FDecl = NULL; - NamedDecl *NDecl = NULL; - DeclarationName UnqualifiedName; if (getLangOptions().CPlusPlus) { // If this is a pseudo-destructor expression, build the call immediately. @@ -2696,20 +3041,33 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs, CommaLocs, RParenLoc)); + Expr *NakedFn = Fn->IgnoreParens(); + + // Determine whether this is a call to an unresolved member function. + if (UnresolvedMemberExpr *MemE = dyn_cast<UnresolvedMemberExpr>(NakedFn)) { + // If lookup was unresolved but not dependent (i.e. didn't find + // an unresolved using declaration), it has to be an overloaded + // function set, which means it must contain either multiple + // declarations (all methods or method templates) or a single + // method template. + assert((MemE->getNumDecls() > 1) || + isa<FunctionTemplateDecl>(*MemE->decls_begin())); + (void)MemE; + + return Owned(BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, + CommaLocs, RParenLoc)); + } + // Determine whether this is a call to a member function. - if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(Fn->IgnoreParens())) { + if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(NakedFn)) { NamedDecl *MemDecl = MemExpr->getMemberDecl(); - if (isa<OverloadedFunctionDecl>(MemDecl) || - isa<CXXMethodDecl>(MemDecl) || - (isa<FunctionTemplateDecl>(MemDecl) && - isa<CXXMethodDecl>( - cast<FunctionTemplateDecl>(MemDecl)->getTemplatedDecl()))) + if (isa<CXXMethodDecl>(MemDecl)) return Owned(BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, CommaLocs, RParenLoc)); } // Determine whether this is a call to a pointer-to-member function. - if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Fn->IgnoreParens())) { + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(NakedFn)) { if (BO->getOpcode() == BinaryOperator::PtrMemD || BO->getOpcode() == BinaryOperator::PtrMemI) { if (const FunctionProtoType *FPT = @@ -2742,48 +3100,65 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, // If we're directly calling a function, get the appropriate declaration. // Also, in C++, keep track of whether we should perform argument-dependent // lookup and whether there were any explicitly-specified template arguments. - bool ADL = true; + llvm::SmallVector<NamedDecl*,8> Fns; + DeclarationName UnqualifiedName; + bool Overloaded; + bool ADL; bool HasExplicitTemplateArgs = 0; - const TemplateArgumentLoc *ExplicitTemplateArgs = 0; - unsigned NumExplicitTemplateArgs = 0; + TemplateArgumentListInfo ExplicitTemplateArgs; NestedNameSpecifier *Qualifier = 0; SourceRange QualifierRange; - DeconstructCallFunction(Fn, NDecl, UnqualifiedName, Qualifier, QualifierRange, - ADL,HasExplicitTemplateArgs, ExplicitTemplateArgs, - NumExplicitTemplateArgs); - - OverloadedFunctionDecl *Ovl = 0; - FunctionTemplateDecl *FunctionTemplate = 0; - if (NDecl) { - FDecl = dyn_cast<FunctionDecl>(NDecl); - if ((FunctionTemplate = dyn_cast<FunctionTemplateDecl>(NDecl))) - FDecl = FunctionTemplate->getTemplatedDecl(); - else - FDecl = dyn_cast<FunctionDecl>(NDecl); - Ovl = dyn_cast<OverloadedFunctionDecl>(NDecl); - } - - if (Ovl || FunctionTemplate || - (getLangOptions().CPlusPlus && (FDecl || UnqualifiedName))) { - // We don't perform ADL for implicit declarations of builtins. - if (FDecl && FDecl->getBuiltinID() && FDecl->isImplicit()) - ADL = false; - - // We don't perform ADL in C. - if (!getLangOptions().CPlusPlus) - ADL = false; - - if (Ovl || FunctionTemplate || ADL) { - FDecl = ResolveOverloadedCallFn(Fn, NDecl, UnqualifiedName, - HasExplicitTemplateArgs, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, - LParenLoc, Args, NumArgs, CommaLocs, - RParenLoc, ADL); - if (!FDecl) - return ExprError(); + DeconstructCallFunction(Fn, Fns, UnqualifiedName, Qualifier, QualifierRange, + ADL, Overloaded, HasExplicitTemplateArgs, + ExplicitTemplateArgs); + + NamedDecl *NDecl; // the specific declaration we're calling, if applicable + FunctionDecl *FDecl; // same, if it's known to be a function + + if (Overloaded || ADL) { +#ifndef NDEBUG + if (ADL) { + // To do ADL, we must have found an unqualified name. + assert(UnqualifiedName && "found no unqualified name for ADL"); + + // We don't perform ADL for implicit declarations of builtins. + // Verify that this was correctly set up. + if (Fns.size() == 1 && (FDecl = dyn_cast<FunctionDecl>(Fns[0])) && + FDecl->getBuiltinID() && FDecl->isImplicit()) + assert(0 && "performing ADL for builtin"); + + // We don't perform ADL in C. + assert(getLangOptions().CPlusPlus && "ADL enabled in C"); + } + + if (Overloaded) { + // To be overloaded, we must either have multiple functions or + // at least one function template (which is effectively an + // infinite set of functions). + assert((Fns.size() > 1 || + (Fns.size() == 1 && + isa<FunctionTemplateDecl>(Fns[0]->getUnderlyingDecl()))) + && "unrecognized overload situation"); + } +#endif + + FDecl = ResolveOverloadedCallFn(Fn, Fns, UnqualifiedName, + (HasExplicitTemplateArgs ? &ExplicitTemplateArgs : 0), + LParenLoc, Args, NumArgs, CommaLocs, + RParenLoc, ADL); + if (!FDecl) + return ExprError(); - Fn = FixOverloadedFunctionReference(Fn, FDecl); + Fn = FixOverloadedFunctionReference(Fn, FDecl); + + NDecl = FDecl; + } else { + assert(Fns.size() <= 1 && "overloaded without Overloaded flag"); + if (Fns.empty()) + NDecl = FDecl = 0; + else { + NDecl = Fns[0]; + FDecl = dyn_cast<FunctionDecl>(NDecl); } } @@ -3198,13 +3573,18 @@ Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, } } -Action::OwningExprResult Sema::ActOnParenListExpr(SourceLocation L, +Action::OwningExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L, SourceLocation R, - MultiExprArg Val) { + MultiExprArg Val, + TypeTy *TypeOfCast) { unsigned nexprs = Val.size(); Expr **exprs = reinterpret_cast<Expr**>(Val.release()); - assert((exprs != 0) && "ActOnParenListExpr() missing expr list"); - Expr *expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R); + assert((exprs != 0) && "ActOnParenOrParenListExpr() missing expr list"); + Expr *expr; + if (nexprs == 1 && TypeOfCast && !TypeIsVectorType(TypeOfCast)) + expr = new (Context) ParenExpr(L, R, exprs[0]); + else + expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R); return Owned(expr); } @@ -3305,6 +3685,17 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast); return RHSTy; } + // And the same for struct objc_selector* / SEL + if (Context.isObjCSelType(LHSTy) && + (RHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) { + ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast); + return LHSTy; + } + if (Context.isObjCSelType(RHSTy) && + (LHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) { + ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast); + return RHSTy; + } // Handle block pointer types. if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) { if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) { @@ -4334,7 +4725,7 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc, const PartialDiagnostic &PD, bool Equality) { // Don't warn if we're in an unevaluated context. - if (ExprEvalContext == Unevaluated) + if (ExprEvalContexts.back().Context == Unevaluated) return; QualType lt = lex->getType(), rt = rex->getType(); @@ -4771,19 +5162,41 @@ inline QualType Sema::CheckBitwiseOperands( inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] Expr *&lex, Expr *&rex, SourceLocation Loc) { - UsualUnaryConversions(lex); - UsualUnaryConversions(rex); + if (!Context.getLangOptions().CPlusPlus) { + UsualUnaryConversions(lex); + UsualUnaryConversions(rex); - if (!lex->getType()->isScalarType() || !rex->getType()->isScalarType()) - return InvalidOperands(Loc, lex, rex); + if (!lex->getType()->isScalarType() || !rex->getType()->isScalarType()) + return InvalidOperands(Loc, lex, rex); - if (Context.getLangOptions().CPlusPlus) { - // C++ [expr.log.and]p2 - // C++ [expr.log.or]p2 - return Context.BoolTy; + return Context.IntTy; } + + // C++ [expr.log.and]p1 + // C++ [expr.log.or]p1 + // The operands are both implicitly converted to type bool (clause 4). + StandardConversionSequence LHS; + if (!IsStandardConversion(lex, Context.BoolTy, + /*InOverloadResolution=*/false, LHS)) + return InvalidOperands(Loc, lex, rex); - return Context.IntTy; + if (PerformImplicitConversion(lex, Context.BoolTy, LHS, + "passing", /*IgnoreBaseAccess=*/false)) + return InvalidOperands(Loc, lex, rex); + + StandardConversionSequence RHS; + if (!IsStandardConversion(rex, Context.BoolTy, + /*InOverloadResolution=*/false, RHS)) + return InvalidOperands(Loc, lex, rex); + + if (PerformImplicitConversion(rex, Context.BoolTy, RHS, + "passing", /*IgnoreBaseAccess=*/false)) + return InvalidOperands(Loc, lex, rex); + + // C++ [expr.log.and]p2 + // C++ [expr.log.or]p2 + // The result is a bool. + return Context.BoolTy; } /// IsReadonlyProperty - Verify that otherwise a valid l-value expression @@ -5123,6 +5536,8 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { // FIXME: Can LHS ever be null here? if (!CheckAddressOfOperand(CO->getTrueExpr(), OpLoc).isNull()) return CheckAddressOfOperand(CO->getFalseExpr(), OpLoc); + } else if (isa<UnresolvedLookupExpr>(op)) { + return Context.OverloadTy; } else if (dcl) { // C99 6.5.3.2p1 // We have an lvalue with a decl. Make sure the decl is not declared // with the register storage-class specifier. @@ -5132,8 +5547,7 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { << "register variable" << op->getSourceRange(); return QualType(); } - } else if (isa<OverloadedFunctionDecl>(dcl) || - isa<FunctionTemplateDecl>(dcl)) { + } else if (isa<FunctionTemplateDecl>(dcl)) { return Context.OverloadTy; } else if (FieldDecl *FD = dyn_cast<FieldDecl>(dcl)) { // Okay: we can take the address of a field. @@ -6199,34 +6613,41 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){ return false; } -Sema::ExpressionEvaluationContext +void Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { - // Introduce a new set of potentially referenced declarations to the stack. - if (NewContext == PotentiallyPotentiallyEvaluated) - PotentiallyReferencedDeclStack.push_back(PotentiallyReferencedDecls()); - - std::swap(ExprEvalContext, NewContext); - return NewContext; + ExprEvalContexts.push_back( + ExpressionEvaluationContextRecord(NewContext, ExprTemporaries.size())); } void -Sema::PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext, - ExpressionEvaluationContext NewContext) { - ExprEvalContext = NewContext; +Sema::PopExpressionEvaluationContext() { + // Pop the current expression evaluation context off the stack. + ExpressionEvaluationContextRecord Rec = ExprEvalContexts.back(); + ExprEvalContexts.pop_back(); - if (OldContext == PotentiallyPotentiallyEvaluated) { + if (Rec.Context == PotentiallyPotentiallyEvaluated && + Rec.PotentiallyReferenced) { // Mark any remaining declarations in the current position of the stack // as "referenced". If they were not meant to be referenced, semantic // analysis would have eliminated them (e.g., in ActOnCXXTypeId). - PotentiallyReferencedDecls RemainingDecls; - RemainingDecls.swap(PotentiallyReferencedDeclStack.back()); - PotentiallyReferencedDeclStack.pop_back(); - - for (PotentiallyReferencedDecls::iterator I = RemainingDecls.begin(), - IEnd = RemainingDecls.end(); + for (PotentiallyReferencedDecls::iterator + I = Rec.PotentiallyReferenced->begin(), + IEnd = Rec.PotentiallyReferenced->end(); I != IEnd; ++I) MarkDeclarationReferenced(I->first, I->second); - } + } + + // When are coming out of an unevaluated context, clear out any + // temporaries that we may have created as part of the evaluation of + // the expression in that context: they aren't relevant because they + // will never be constructed. + if (Rec.Context == Unevaluated && + ExprTemporaries.size() > Rec.NumTemporaries) + ExprTemporaries.erase(ExprTemporaries.begin() + Rec.NumTemporaries, + ExprTemporaries.end()); + + // Destroy the popped expression evaluation record. + Rec.Destroy(); } /// \brief Note that the given declaration was referenced in the source code. @@ -6258,7 +6679,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { if (CurContext->isDependentContext()) return; - switch (ExprEvalContext) { + switch (ExprEvalContexts.back().Context) { case Unevaluated: // We are in an expression that is not potentially evaluated; do nothing. return; @@ -6272,7 +6693,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { // We are in an expression that may be potentially evaluated; queue this // declaration reference until we know whether the expression is // potentially evaluated. - PotentiallyReferencedDeclStack.back().push_back(std::make_pair(Loc, D)); + ExprEvalContexts.back().addReferencedDecl(Loc, D); return; } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 462bf13..00fb65d 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -63,10 +63,11 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, } } - // If this is an unevaluated operand, clear out the set of declaration - // references we have been computing. + // If this is an unevaluated operand, clear out the set of + // declaration references we have been computing and eliminate any + // temporaries introduced in its computation. if (isUnevaluatedOperand) - PotentiallyReferencedDeclStack.back().clear(); + ExprEvalContexts.back().Context = Unevaluated; } return Owned(new (Context) CXXTypeidExpr(isType, TyOrExpr, @@ -326,7 +327,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, &DInfo); if (D.isInvalidType()) return ExprError(); - + return BuildCXXNew(StartLoc, UseGlobal, PlacementLParen, move(PlacementArgs), @@ -394,7 +395,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, FunctionDecl *OperatorDelete = 0; Expr **PlaceArgs = (Expr**)PlacementArgs.get(); unsigned NumPlaceArgs = PlacementArgs.size(); - + if (!AllocType->isDependentType() && !Expr::hasAnyTypeDependentArguments(PlaceArgs, NumPlaceArgs) && FindAllocationFunctions(StartLoc, @@ -402,7 +403,24 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, UseGlobal, AllocType, ArraySize, PlaceArgs, NumPlaceArgs, OperatorNew, OperatorDelete)) return ExprError(); - + llvm::SmallVector<Expr *, 8> AllPlaceArgs; + if (OperatorNew) { + // Add default arguments, if any. + const FunctionProtoType *Proto = + OperatorNew->getType()->getAs<FunctionProtoType>(); + VariadicCallType CallType = + Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply; + bool Invalid = GatherArgumentsForCall(PlacementLParen, OperatorNew, + Proto, 1, PlaceArgs, NumPlaceArgs, + AllPlaceArgs, CallType); + if (Invalid) + return ExprError(); + + NumPlaceArgs = AllPlaceArgs.size(); + if (NumPlaceArgs > 0) + PlaceArgs = &AllPlaceArgs[0]; + } + bool Init = ConstructorLParen.isValid(); // --- Choosing a constructor --- // C++ 5.3.4p15 @@ -602,7 +620,9 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, // The first argument is size_t, and the first parameter must be size_t, // too. This is checked on declaration and can be assumed. (It can't be // asserted on, though, since invalid decls are left in there.) - for (unsigned i = 0; i < NumArgs; ++i) { + // Whatch out for variadic allocator function. + unsigned NumArgsInFnDecl = FnDecl->getNumParams(); + for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) { // FIXME: Passing word to diagnostic. if (PerformCopyInitialization(Args[i], FnDecl->getParamDecl(i)->getType(), @@ -827,18 +847,15 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, if (const RecordType *Record = Type->getAs<RecordType>()) { llvm::SmallVector<CXXConversionDecl *, 4> ObjectPtrConversions; CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); - OverloadedFunctionDecl *Conversions = - RD->getVisibleConversionFunctions(); + const UnresolvedSet *Conversions = RD->getVisibleConversionFunctions(); - for (OverloadedFunctionDecl::function_iterator - Func = Conversions->function_begin(), - FuncEnd = Conversions->function_end(); - Func != FuncEnd; ++Func) { + for (UnresolvedSet::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { // Skip over templated conversion functions; they aren't considered. - if (isa<FunctionTemplateDecl>(*Func)) + if (isa<FunctionTemplateDecl>(*I)) continue; - CXXConversionDecl *Conv = cast<CXXConversionDecl>(*Func); + CXXConversionDecl *Conv = cast<CXXConversionDecl>(*I); QualType ConvType = Conv->getConversionType().getNonReferenceType(); if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>()) @@ -927,54 +944,25 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, OperatorDelete, Ex, StartLoc)); } - -/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a -/// C++ if/switch/while/for statement. -/// e.g: "if (int x = f()) {...}" -Action::OwningExprResult -Sema::ActOnCXXConditionDeclarationExpr(Scope *S, SourceLocation StartLoc, - Declarator &D, - SourceLocation EqualLoc, - ExprArg AssignExprVal) { - assert(AssignExprVal.get() && "Null assignment expression"); - - // C++ 6.4p2: - // The declarator shall not specify a function or an array. - // The type-specifier-seq shall not contain typedef and shall not declare a - // new class or enumeration. - - assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && - "Parser allowed 'typedef' as storage class of condition decl."); - - // FIXME: Store DeclaratorInfo in the expression. - DeclaratorInfo *DInfo = 0; - TagDecl *OwnedTag = 0; - QualType Ty = GetTypeForDeclarator(D, S, &DInfo, &OwnedTag); - - if (Ty->isFunctionType()) { // The declarator shall not specify a function... - // We exit without creating a CXXConditionDeclExpr because a FunctionDecl - // would be created and CXXConditionDeclExpr wants a VarDecl. - return ExprError(Diag(StartLoc, diag::err_invalid_use_of_function_type) - << SourceRange(StartLoc, EqualLoc)); - } else if (Ty->isArrayType()) { // ...or an array. - Diag(StartLoc, diag::err_invalid_use_of_array_type) - << SourceRange(StartLoc, EqualLoc); - } else if (OwnedTag && OwnedTag->isDefinition()) { - // The type-specifier-seq shall not declare a new class or enumeration. - Diag(OwnedTag->getLocation(), diag::err_type_defined_in_condition); - } - - DeclPtrTy Dcl = ActOnDeclarator(S, D); - if (!Dcl) - return ExprError(); - AddInitializerToDecl(Dcl, move(AssignExprVal), /*DirectInit=*/false); - - // Mark this variable as one that is declared within a conditional. - // We know that the decl had to be a VarDecl because that is the only type of - // decl that can be assigned and the grammar requires an '='. - VarDecl *VD = cast<VarDecl>(Dcl.getAs<Decl>()); - VD->setDeclaredInCondition(true); - return Owned(new (Context) CXXConditionDeclExpr(StartLoc, EqualLoc, VD)); +/// \brief Check the use of the given variable as a C++ condition in an if, +/// while, do-while, or switch statement. +Action::OwningExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar) { + QualType T = ConditionVar->getType(); + + // C++ [stmt.select]p2: + // The declarator shall not specify a function or an array. + if (T->isFunctionType()) + return ExprError(Diag(ConditionVar->getLocation(), + diag::err_invalid_use_of_function_type) + << ConditionVar->getSourceRange()); + else if (T->isArrayType()) + return ExprError(Diag(ConditionVar->getLocation(), + diag::err_invalid_use_of_array_type) + << ConditionVar->getSourceRange()); + + return Owned(DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar, + ConditionVar->getLocation(), + ConditionVar->getType().getNonReferenceType())); } /// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid. @@ -1128,11 +1116,12 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, dyn_cast<CXXConstructorDecl>(FD)) { CastKind = CastExpr::CK_ConstructorConversion; // Do no conversion if dealing with ... for the first conversion. - if (!ICS.UserDefined.EllipsisConversion) + if (!ICS.UserDefined.EllipsisConversion) { // If the user-defined conversion is specified by a constructor, the // initial standard conversion sequence converts the source type to the // type required by the argument of the constructor - BeforeToType = Ctor->getParamDecl(0)->getType(); + BeforeToType = Ctor->getParamDecl(0)->getType().getNonReferenceType(); + } } else assert(0 && "Unknown conversion function kind!"); @@ -1152,21 +1141,25 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, if (CastArg.isInvalid()) return true; - + + From = CastArg.takeAs<Expr>(); + + // FIXME: This and the following if statement shouldn't be necessary, but + // there's some nasty stuff involving MaybeBindToTemporary going on here. if (ICS.UserDefined.After.Second == ICK_Derived_To_Base && ICS.UserDefined.After.CopyConstructor) { - From = CastArg.takeAs<Expr>(); return BuildCXXDerivedToBaseExpr(From, CastKind, ICS, Flavor); } - - if (ICS.UserDefined.After.Second == ICK_Pointer_Member && - ToType.getNonReferenceType()->isMemberFunctionPointerType()) - CastKind = CastExpr::CK_BaseToDerivedMemberPointer; - - From = new (Context) ImplicitCastExpr(ToType.getNonReferenceType(), - CastKind, CastArg.takeAs<Expr>(), - ToType->isLValueReferenceType()); - return false; + + if (ICS.UserDefined.After.CopyConstructor) { + From = new (Context) ImplicitCastExpr(ToType.getNonReferenceType(), + CastKind, From, + ToType->isLValueReferenceType()); + return false; + } + + return PerformImplicitConversion(From, ToType, ICS.UserDefined.After, + "converting", IgnoreBaseAccess); } case ImplicitConversionSequence::EllipsisConversion: @@ -1333,9 +1326,14 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, ImpCastExprToType(From, ToType, Kind); break; } - case ICK_Boolean_Conversion: - ImpCastExprToType(From, Context.BoolTy, CastExpr::CK_Unknown); + case ICK_Boolean_Conversion: { + CastExpr::CastKind Kind = CastExpr::CK_Unknown; + if (FromType->isMemberPointerType()) + Kind = CastExpr::CK_MemberPointerToBoolean; + + ImpCastExprToType(From, Context.BoolTy, Kind); break; + } case ICK_Derived_To_Base: if (CheckDerivedToBaseConversion(From->getType(), @@ -2131,10 +2129,10 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc, return ExprError(); } } - } - if (BaseType->isPointerType()) - BaseType = BaseType->getPointeeType(); + if (BaseType->isPointerType()) + BaseType = BaseType->getPointeeType(); + } // We could end up with various non-record types here, such as extended // vector types or Objective-C interfaces. Just return early and let @@ -2175,10 +2173,10 @@ CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, else ResultType = Method->getResultType().getNonReferenceType(); - CXXMemberCallExpr *CE = - new (Context) CXXMemberCallExpr(Context, ME, 0, 0, - ResultType, - Exp->getLocEnd()); + MarkDeclarationReferenced(Exp->getLocStart(), Method); + CXXMemberCallExpr *CE = + new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, + Exp->getLocEnd()); return CE; } @@ -2238,9 +2236,6 @@ Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) { /// /// FIXME: Should Objective-C also use this approach? /// -/// \param SS if non-NULL, the C++ nested-name-specifier that precedes the -/// name of the declaration referenced. -/// /// \param D the declaration being referenced from the current scope. /// /// \param NameLoc the location of the name in the source. @@ -2249,16 +2244,11 @@ Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) { /// access, will be set to the type of the "this" pointer to be used when /// building that implicit member access. /// -/// \param MemberType if the reference to this declaration is an implicit -/// member access, will be set to the type of the member being referenced -/// (for use at the type of the resulting member access expression). -/// /// \returns true if this is an implicit member reference (in which case /// \p ThisType and \p MemberType will be set), or false if it is not an /// implicit member reference. -bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D, - SourceLocation NameLoc, QualType &ThisType, - QualType &MemberType) { +bool Sema::isImplicitMemberReference(const LookupResult &R, + QualType &ThisType) { // If this isn't a C++ method, then it isn't an implicit member reference. CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext); if (!MD || MD->isStatic()) @@ -2271,30 +2261,21 @@ bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D, // class member access expression (5.2.5) using (*this) (9.3.2) // as the postfix-expression to the left of the '.' operator. DeclContext *Ctx = 0; - if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { + if (R.isUnresolvableResult()) { + // FIXME: this is just picking one at random + Ctx = R.getRepresentativeDecl()->getDeclContext(); + } else if (FieldDecl *FD = R.getAsSingle<FieldDecl>()) { Ctx = FD->getDeclContext(); - MemberType = FD->getType(); - - if (const ReferenceType *RefType = MemberType->getAs<ReferenceType>()) - MemberType = RefType->getPointeeType(); - else if (!FD->isMutable()) - MemberType - = Context.getQualifiedType(MemberType, - Qualifiers::fromCVRMask(MD->getTypeQualifiers())); } else { - for (OverloadIterator Ovl(D), OvlEnd; Ovl != OvlEnd; ++Ovl) { - CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*I); FunctionTemplateDecl *FunTmpl = 0; - if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl))) + if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*I))) Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); // FIXME: Do we have to know if there are explicit template arguments? if (Method && !Method->isStatic()) { Ctx = Method->getParent(); - if (isa<CXXMethodDecl>(D) && !FunTmpl) - MemberType = Method->getType(); - else - MemberType = Context.OverloadTy; break; } } @@ -2306,11 +2287,8 @@ bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D, // Determine whether the declaration(s) we found are actually in a base // class. If not, this isn't an implicit member reference. ThisType = MD->getThisType(Context); - - // If the type of "this" is dependent, we can't tell if the member is in a - // base class or not, so treat this as a dependent implicit member reference. - if (ThisType->isDependentType()) - return true; + + // FIXME: this doesn't really work for overloaded lookups. QualType CtxType = Context.getTypeDeclType(cast<CXXRecordDecl>(Ctx)); QualType ClassType diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 0f973d6d..2eba704 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -136,8 +136,51 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType, SourceLocation InitLoc, DeclarationName InitEntity, bool DirectInit) { if (DeclType->isDependentType() || - Init->isTypeDependent() || Init->isValueDependent()) + Init->isTypeDependent() || Init->isValueDependent()) { + // We have either a dependent type or a type- or value-dependent + // initializer, so we don't perform any additional checking at + // this point. + + // If the declaration is a non-dependent, incomplete array type + // that has an initializer, then its type will be completed once + // the initializer is instantiated. + if (!DeclType->isDependentType()) { + if (const IncompleteArrayType *ArrayT + = Context.getAsIncompleteArrayType(DeclType)) { + if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { + if (!ILE->isTypeDependent()) { + // Compute the constant array type from the length of the + // initializer list. + // FIXME: This will be wrong if there are designated + // initializations. Good thing they don't exist in C++! + llvm::APInt NumElements(Context.getTypeSize(Context.getSizeType()), + ILE->getNumInits()); + llvm::APInt Zero(Context.getTypeSize(Context.getSizeType()), 0); + if (NumElements == Zero) { + // Sizing an array implicitly to zero is not allowed by ISO C, + // but is supported by GNU. + Diag(ILE->getLocStart(), diag::ext_typecheck_zero_array_size); + } + + DeclType = Context.getConstantArrayType(ArrayT->getElementType(), + NumElements, + ArrayT->getSizeModifier(), + ArrayT->getIndexTypeCVRQualifiers()); + return false; + } + } + + // Make the array type-dependent by making it dependently-sized. + DeclType = Context.getDependentSizedArrayType(ArrayT->getElementType(), + /*NumElts=*/0, + ArrayT->getSizeModifier(), + ArrayT->getIndexTypeCVRQualifiers(), + SourceRange()); + } + } + return false; + } // C++ [dcl.init.ref]p1: // A variable declared to be a T& or T&&, that is "reference to type T" diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 1957d7f..8f09827 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -242,6 +242,7 @@ void LookupResult::deletePaths(CXXBasePaths *Paths) { delete Paths; } +/// Resolves the result kind of this lookup. void LookupResult::resolveKind() { unsigned N = Decls.size(); @@ -251,8 +252,12 @@ void LookupResult::resolveKind() { return; } + // If there's a single decl, we need to examine it to decide what + // kind of lookup this is. if (N == 1) { - if (isa<UnresolvedUsingValueDecl>(Decls[0])) + if (isa<FunctionTemplateDecl>(Decls[0])) + ResultKind = FoundOverloaded; + else if (isa<UnresolvedUsingValueDecl>(Decls[0])) ResultKind = FoundUnresolvedValue; return; } @@ -264,7 +269,7 @@ void LookupResult::resolveKind() { bool Ambiguous = false; bool HasTag = false, HasFunction = false, HasNonFunction = false; - bool HasUnresolved = false; + bool HasFunctionTemplate = false, HasUnresolved = false; unsigned UniqueTagIndex = 0; @@ -290,7 +295,10 @@ void LookupResult::resolveKind() { Ambiguous = true; UniqueTagIndex = I; HasTag = true; - } else if (D->isFunctionOrFunctionTemplate()) { + } else if (isa<FunctionTemplateDecl>(D)) { + HasFunction = true; + HasFunctionTemplate = true; + } else if (isa<FunctionDecl>(D)) { HasFunction = true; } else { if (HasNonFunction) @@ -323,7 +331,7 @@ void LookupResult::resolveKind() { setAmbiguous(LookupResult::AmbiguousReference); else if (HasUnresolved) ResultKind = LookupResult::FoundUnresolvedValue; - else if (N > 1) + else if (N > 1 || HasFunctionTemplate) ResultKind = LookupResult::FoundOverloaded; else ResultKind = LookupResult::Found; @@ -1525,33 +1533,25 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, // in which the function or function template is defined and the // classes and namespaces associated with its (non-dependent) // parameter types and return type. - DeclRefExpr *DRE = 0; - TemplateIdRefExpr *TIRE = 0; Arg = Arg->IgnoreParens(); - if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg)) { - if (unaryOp->getOpcode() == UnaryOperator::AddrOf) { - DRE = dyn_cast<DeclRefExpr>(unaryOp->getSubExpr()); - TIRE = dyn_cast<TemplateIdRefExpr>(unaryOp->getSubExpr()); - } - } else { - DRE = dyn_cast<DeclRefExpr>(Arg); - TIRE = dyn_cast<TemplateIdRefExpr>(Arg); - } + if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg)) + if (unaryOp->getOpcode() == UnaryOperator::AddrOf) + Arg = unaryOp->getSubExpr(); + + // TODO: avoid the copies. This should be easy when the cases + // share a storage implementation. + llvm::SmallVector<NamedDecl*, 8> Functions; - OverloadedFunctionDecl *Ovl = 0; - if (DRE) - Ovl = dyn_cast<OverloadedFunctionDecl>(DRE->getDecl()); - else if (TIRE) - Ovl = TIRE->getTemplateName().getAsOverloadedFunctionDecl(); - if (!Ovl) + if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg)) + Functions.append(ULE->decls_begin(), ULE->decls_end()); + else continue; - for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(), - FuncEnd = Ovl->function_end(); - Func != FuncEnd; ++Func) { - FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*Func); + for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Functions.begin(), + E = Functions.end(); I != E; ++I) { + FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*I); if (!FDecl) - FDecl = cast<FunctionTemplateDecl>(*Func)->getTemplatedDecl(); + FDecl = cast<FunctionTemplateDecl>(*I)->getTemplatedDecl(); // Add the namespace in which this function was defined. Note // that, if this is a member function, we do *not* consider the diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index daf5b7f..6ea6a14 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -23,7 +23,6 @@ #include "clang/Basic/PartialDiagnostic.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Support/Compiler.h" #include <algorithm> #include <cstdio> @@ -1353,18 +1352,6 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType) { return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType); } -/// \brief Given a function template or function, extract the function template -/// declaration (if any) and the underlying function declaration. -template<typename T> -static void GetFunctionAndTemplate(AnyFunctionDecl Orig, T *&Function, - FunctionTemplateDecl *&FunctionTemplate) { - FunctionTemplate = dyn_cast<FunctionTemplateDecl>(Orig); - if (FunctionTemplate) - Function = cast<T>(FunctionTemplate->getTemplatedDecl()); - else - Function = cast<T>(Orig); -} - /// Determines whether there is a user-defined conversion sequence /// (C++ [over.ics.user]) that converts expression From to the type /// ToType. If such a conversion exists, User will contain the @@ -1431,8 +1418,8 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion( if (!Constructor->isInvalidDecl() && Constructor->isConvertingConstructor(AllowExplicit)) { if (ConstructorTmpl) - AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0, &From, - 1, CandidateSet, + AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0, + &From, 1, CandidateSet, SuppressUserConversions, ForceRValue); else // Allow one user-defined conversion when user specifies a @@ -1455,18 +1442,16 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion( if (CXXRecordDecl *FromRecordDecl = dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) { // Add all of the conversion functions as candidates. - OverloadedFunctionDecl *Conversions + const UnresolvedSet *Conversions = FromRecordDecl->getVisibleConversionFunctions(); - for (OverloadedFunctionDecl::function_iterator Func - = Conversions->function_begin(); - Func != Conversions->function_end(); ++Func) { + for (UnresolvedSet::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { CXXConversionDecl *Conv; FunctionTemplateDecl *ConvTemplate; - GetFunctionAndTemplate(*Func, Conv, ConvTemplate); - if (ConvTemplate) + if ((ConvTemplate = dyn_cast<FunctionTemplateDecl>(*I))) Conv = dyn_cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); else - Conv = dyn_cast<CXXConversionDecl>(*Func); + Conv = dyn_cast<CXXConversionDecl>(*I); if (AllowExplicit || !Conv->isExplicit()) { if (ConvTemplate) @@ -2254,6 +2239,9 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, if (!CandidateSet.isNewCandidate(Function)) return; + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated); + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function)){ // C++ [class.copy]p3: // A member function template is never instantiated to perform the copy @@ -2365,13 +2353,13 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions, if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) && !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) AddMethodTemplateCandidate(FunTmpl, - /*FIXME: explicit args */false, 0, 0, + /*FIXME: explicit args */ 0, Args[0], Args + 1, NumArgs - 1, CandidateSet, SuppressUserConversions); else AddTemplateOverloadCandidate(FunTmpl, - /*FIXME: explicit args */false, 0, 0, + /*FIXME: explicit args */ 0, Args, NumArgs, CandidateSet, SuppressUserConversions); } @@ -2394,7 +2382,7 @@ void Sema::AddMethodCandidate(NamedDecl *Decl, Expr *Object, if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) { assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) && "Expected a member function template"); - AddMethodTemplateCandidate(TD, false, 0, 0, + AddMethodTemplateCandidate(TD, /*ExplicitArgs*/ 0, Object, Args, NumArgs, CandidateSet, SuppressUserConversions, @@ -2430,6 +2418,9 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object, if (!CandidateSet.isNewCandidate(Method)) return; + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated); + // Add this candidate CandidateSet.push_back(OverloadCandidate()); OverloadCandidate& Candidate = CandidateSet.back(); @@ -2509,9 +2500,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object, /// function template specialization. void Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo *ExplicitTemplateArgs, Expr *Object, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions, @@ -2531,8 +2520,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, TemplateDeductionInfo Info(Context); FunctionDecl *Specialization = 0; if (TemplateDeductionResult Result - = DeduceTemplateArguments(MethodTmpl, HasExplicitTemplateArgs, - ExplicitTemplateArgs, NumExplicitTemplateArgs, + = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args, NumArgs, Specialization, Info)) { // FIXME: Record what happened with template argument deduction, so // that we can give the user a beautiful diagnostic. @@ -2554,9 +2542,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, /// an appropriate function template specialization. void Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions, @@ -2576,8 +2562,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, TemplateDeductionInfo Info(Context); FunctionDecl *Specialization = 0; if (TemplateDeductionResult Result - = DeduceTemplateArguments(FunctionTemplate, HasExplicitTemplateArgs, - ExplicitTemplateArgs, NumExplicitTemplateArgs, + = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args, NumArgs, Specialization, Info)) { // FIXME: Record what happened with template argument deduction, so // that we can give the user a beautiful diagnostic. @@ -2608,6 +2593,9 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, if (!CandidateSet.isNewCandidate(Conversion)) return; + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated); + // Add this candidate CandidateSet.push_back(OverloadCandidate()); OverloadCandidate& Candidate = CandidateSet.back(); @@ -2732,6 +2720,9 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, if (!CandidateSet.isNewCandidate(Conversion)) return; + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated); + CandidateSet.push_back(OverloadCandidate()); OverloadCandidate& Candidate = CandidateSet.back(); Candidate.Function = 0; @@ -2897,6 +2888,9 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, OverloadCandidateSet& CandidateSet, bool IsAssignmentOperator, unsigned NumContextualBoolArguments) { + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated); + // Add this candidate CandidateSet.push_back(OverloadCandidate()); OverloadCandidate& Candidate = CandidateSet.back(); @@ -3144,20 +3138,17 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, } CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); - OverloadedFunctionDecl *Conversions + const UnresolvedSet *Conversions = ClassDecl->getVisibleConversionFunctions(); - for (OverloadedFunctionDecl::function_iterator Func - = Conversions->function_begin(); - Func != Conversions->function_end(); ++Func) { - CXXConversionDecl *Conv; - FunctionTemplateDecl *ConvTemplate; - GetFunctionAndTemplate(*Func, Conv, ConvTemplate); + for (UnresolvedSet::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { // Skip conversion function templates; they don't tell us anything // about which builtin types we can convert to. - if (ConvTemplate) + if (isa<FunctionTemplateDecl>(*I)) continue; + CXXConversionDecl *Conv = cast<CXXConversionDecl>(*I); if (AllowExplicitConversions || !Conv->isExplicit()) { AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false, VisibleQuals); @@ -3211,13 +3202,12 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { } CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); - OverloadedFunctionDecl *Conversions = + const UnresolvedSet *Conversions = ClassDecl->getVisibleConversionFunctions(); - for (OverloadedFunctionDecl::function_iterator Func - = Conversions->function_begin(); - Func != Conversions->function_end(); ++Func) { - if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(*Func)) { + for (UnresolvedSet::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(*I)) { QualType CanTy = Context.getCanonicalType(Conv->getConversionType()); if (const ReferenceType *ResTypeRef = CanTy->getAs<ReferenceType>()) CanTy = ResTypeRef->getPointeeType(); @@ -3959,9 +3949,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, void Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, Expr **Args, unsigned NumArgs, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, bool PartialOverloading) { FunctionSet Functions; @@ -4000,16 +3988,14 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, FuncEnd = Functions.end(); Func != FuncEnd; ++Func) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func)) { - if (HasExplicitTemplateArgs) + if (ExplicitTemplateArgs) continue; AddOverloadCandidate(FD, Args, NumArgs, CandidateSet, false, false, PartialOverloading); } else AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*Func), - HasExplicitTemplateArgs, ExplicitTemplateArgs, - NumExplicitTemplateArgs, Args, NumArgs, CandidateSet); } } @@ -4336,7 +4322,6 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, return 0; // Find the actual overloaded function declaration. - OverloadedFunctionDecl *Ovl = 0; // C++ [over.over]p1: // [...] [Note: any redundant set of parentheses surrounding the @@ -4352,50 +4337,37 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, } bool HasExplicitTemplateArgs = false; - const TemplateArgumentLoc *ExplicitTemplateArgs = 0; - unsigned NumExplicitTemplateArgs = 0; + TemplateArgumentListInfo ExplicitTemplateArgs; + + llvm::SmallVector<NamedDecl*,8> Fns; - // Try to dig out the overloaded function. - FunctionTemplateDecl *FunctionTemplate = 0; - if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr)) { - Ovl = dyn_cast<OverloadedFunctionDecl>(DR->getDecl()); - FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DR->getDecl()); - HasExplicitTemplateArgs = DR->hasExplicitTemplateArgumentList(); - ExplicitTemplateArgs = DR->getTemplateArgs(); - NumExplicitTemplateArgs = DR->getNumTemplateArgs(); - } else if (MemberExpr *ME = dyn_cast<MemberExpr>(OvlExpr)) { - Ovl = dyn_cast<OverloadedFunctionDecl>(ME->getMemberDecl()); - FunctionTemplate = dyn_cast<FunctionTemplateDecl>(ME->getMemberDecl()); - HasExplicitTemplateArgs = ME->hasExplicitTemplateArgumentList(); - ExplicitTemplateArgs = ME->getTemplateArgs(); - NumExplicitTemplateArgs = ME->getNumTemplateArgs(); - } else if (TemplateIdRefExpr *TIRE = dyn_cast<TemplateIdRefExpr>(OvlExpr)) { - TemplateName Name = TIRE->getTemplateName(); - Ovl = Name.getAsOverloadedFunctionDecl(); - FunctionTemplate = - dyn_cast_or_null<FunctionTemplateDecl>(Name.getAsTemplateDecl()); - - HasExplicitTemplateArgs = true; - ExplicitTemplateArgs = TIRE->getTemplateArgs(); - NumExplicitTemplateArgs = TIRE->getNumTemplateArgs(); + // Look into the overloaded expression. + if (UnresolvedLookupExpr *UL + = dyn_cast<UnresolvedLookupExpr>(OvlExpr)) { + Fns.append(UL->decls_begin(), UL->decls_end()); + if (UL->hasExplicitTemplateArgs()) { + HasExplicitTemplateArgs = true; + UL->copyTemplateArgumentsInto(ExplicitTemplateArgs); + } + } else if (UnresolvedMemberExpr *ME + = dyn_cast<UnresolvedMemberExpr>(OvlExpr)) { + Fns.append(ME->decls_begin(), ME->decls_end()); + if (ME->hasExplicitTemplateArgs()) { + HasExplicitTemplateArgs = true; + ME->copyTemplateArgumentsInto(ExplicitTemplateArgs); + } } - - // If there's no overloaded function declaration or function template, - // we're done. - if (!Ovl && !FunctionTemplate) - return 0; - OverloadIterator Fun; - if (Ovl) - Fun = Ovl; - else - Fun = FunctionTemplate; + // If we didn't actually find anything, we're done. + if (Fns.empty()) + return 0; // Look through all of the overloaded functions, searching for one // whose type matches exactly. llvm::SmallPtrSet<FunctionDecl *, 4> Matches; bool FoundNonTemplateFunction = false; - for (OverloadIterator FunEnd; Fun != FunEnd; ++Fun) { + for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Fns.begin(), + E = Fns.end(); I != E; ++I) { // C++ [over.over]p3: // Non-member functions and static member functions match // targets of type "pointer-to-function" or "reference-to-function." @@ -4404,7 +4376,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // Note that according to DR 247, the containing class does not matter. if (FunctionTemplateDecl *FunctionTemplate - = dyn_cast<FunctionTemplateDecl>(*Fun)) { + = dyn_cast<FunctionTemplateDecl>(*I)) { if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) { // Skip non-static function templates when converting to pointer, and @@ -4424,9 +4396,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, FunctionDecl *Specialization = 0; TemplateDeductionInfo Info(Context); if (TemplateDeductionResult Result - = DeduceTemplateArguments(FunctionTemplate, HasExplicitTemplateArgs, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, + = DeduceTemplateArguments(FunctionTemplate, + (HasExplicitTemplateArgs ? &ExplicitTemplateArgs : 0), FunctionType, Specialization, Info)) { // FIXME: make a note of the failed deduction for diagnostics. (void)Result; @@ -4438,9 +4409,11 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, Matches.insert( cast<FunctionDecl>(Specialization->getCanonicalDecl())); } + + continue; } - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Fun)) { + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*I)) { // Skip non-static functions when converting to pointer, and static // when converting to member pointer. if (Method->isStatic() == IsMember) @@ -4452,9 +4425,9 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, } else if (IsMember) continue; - if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Fun)) { + if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*I)) { if (FunctionType == Context.getCanonicalType(FunDecl->getType())) { - Matches.insert(cast<FunctionDecl>(Fun->getCanonicalDecl())); + Matches.insert(cast<FunctionDecl>(FunDecl->getCanonicalDecl())); FoundNonTemplateFunction = true; } } @@ -4522,51 +4495,47 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, /// \brief Add a single candidate to the overload set. static void AddOverloadedCallCandidate(Sema &S, - AnyFunctionDecl Callee, - bool &ArgumentDependentLookup, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + NamedDecl *Callee, + const TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, bool PartialOverloading) { + if (isa<UsingShadowDecl>(Callee)) + Callee = cast<UsingShadowDecl>(Callee)->getTargetDecl(); + if (FunctionDecl *Func = dyn_cast<FunctionDecl>(Callee)) { - assert(!HasExplicitTemplateArgs && "Explicit template arguments?"); + assert(!ExplicitTemplateArgs && "Explicit template arguments?"); S.AddOverloadCandidate(Func, Args, NumArgs, CandidateSet, false, false, PartialOverloading); - - if (Func->getDeclContext()->isRecord() || - Func->getDeclContext()->isFunctionOrMethod()) - ArgumentDependentLookup = false; return; - } - - FunctionTemplateDecl *FuncTemplate = cast<FunctionTemplateDecl>(Callee); - S.AddTemplateOverloadCandidate(FuncTemplate, HasExplicitTemplateArgs, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, - Args, NumArgs, CandidateSet); - - if (FuncTemplate->getDeclContext()->isRecord()) - ArgumentDependentLookup = false; + } + + if (FunctionTemplateDecl *FuncTemplate + = dyn_cast<FunctionTemplateDecl>(Callee)) { + S.AddTemplateOverloadCandidate(FuncTemplate, ExplicitTemplateArgs, + Args, NumArgs, CandidateSet); + return; + } + + assert(false && "unhandled case in overloaded call candidate"); + + // do nothing? } /// \brief Add the overload candidates named by callee and/or found by argument /// dependent lookup to the given overload set. -void Sema::AddOverloadedCallCandidates(NamedDecl *Callee, +void Sema::AddOverloadedCallCandidates(llvm::SmallVectorImpl<NamedDecl*> &Fns, DeclarationName &UnqualifiedName, - bool &ArgumentDependentLookup, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + bool ArgumentDependentLookup, + const TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, bool PartialOverloading) { - // Add the functions denoted by Callee to the set of candidate - // functions. While we're doing so, track whether argument-dependent - // lookup still applies, per: + +#ifndef NDEBUG + // Verify that ArgumentDependentLookup is consistent with the rules + // in C++0x [basic.lookup.argdep]p3: // - // C++0x [basic.lookup.argdep]p3: // Let X be the lookup set produced by unqualified lookup (3.4.1) // and let Y be the lookup set produced by argument dependent // lookup (defined as follows). If X contains @@ -4574,43 +4543,32 @@ void Sema::AddOverloadedCallCandidates(NamedDecl *Callee, // -- a declaration of a class member, or // // -- a block-scope function declaration that is not a - // using-declaration (FIXME: check for using declaration), or + // using-declaration, or // // -- a declaration that is neither a function or a function // template // // then Y is empty. - if (!Callee) { - // Nothing to do. - } else if (OverloadedFunctionDecl *Ovl - = dyn_cast<OverloadedFunctionDecl>(Callee)) { - for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(), - FuncEnd = Ovl->function_end(); - Func != FuncEnd; ++Func) - AddOverloadedCallCandidate(*this, *Func, ArgumentDependentLookup, - HasExplicitTemplateArgs, - ExplicitTemplateArgs, NumExplicitTemplateArgs, - Args, NumArgs, CandidateSet, - PartialOverloading); - } else if (isa<FunctionDecl>(Callee) || isa<FunctionTemplateDecl>(Callee)) - AddOverloadedCallCandidate(*this, - AnyFunctionDecl::getFromNamedDecl(Callee), - ArgumentDependentLookup, - HasExplicitTemplateArgs, - ExplicitTemplateArgs, NumExplicitTemplateArgs, - Args, NumArgs, CandidateSet, + + if (ArgumentDependentLookup) { + for (unsigned I = 0; I < Fns.size(); ++I) { + assert(!Fns[I]->getDeclContext()->isRecord()); + assert(isa<UsingShadowDecl>(Fns[I]) || + !Fns[I]->getDeclContext()->isFunctionOrMethod()); + assert(Fns[I]->getUnderlyingDecl()->isFunctionOrFunctionTemplate()); + } + } +#endif + + for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Fns.begin(), + E = Fns.end(); I != E; ++I) + AddOverloadedCallCandidate(*this, *I, ExplicitTemplateArgs, + Args, NumArgs, CandidateSet, PartialOverloading); - // FIXME: assert isa<FunctionDecl> || isa<FunctionTemplateDecl> rather than - // checking dynamically. - - if (Callee) - UnqualifiedName = Callee->getDeclName(); - + if (ArgumentDependentLookup) AddArgumentDependentLookupCandidates(UnqualifiedName, Args, NumArgs, - HasExplicitTemplateArgs, ExplicitTemplateArgs, - NumExplicitTemplateArgs, CandidateSet, PartialOverloading); } @@ -4622,23 +4580,21 @@ void Sema::AddOverloadedCallCandidates(NamedDecl *Callee, /// the function declaration produced by overload /// resolution. Otherwise, emits diagnostics, deletes all of the /// arguments and Fn, and returns NULL. -FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, +FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, + llvm::SmallVectorImpl<NamedDecl*> &Fns, DeclarationName UnqualifiedName, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo *ExplicitTemplateArgs, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation *CommaLocs, SourceLocation RParenLoc, - bool &ArgumentDependentLookup) { + bool ArgumentDependentLookup) { OverloadCandidateSet CandidateSet; // Add the functions denoted by Callee to the set of candidate // functions. - AddOverloadedCallCandidates(Callee, UnqualifiedName, ArgumentDependentLookup, - HasExplicitTemplateArgs, ExplicitTemplateArgs, - NumExplicitTemplateArgs, Args, NumArgs, + AddOverloadedCallCandidates(Fns, UnqualifiedName, ArgumentDependentLookup, + ExplicitTemplateArgs, Args, NumArgs, CandidateSet); OverloadCandidateSet::iterator Best; switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) { @@ -4675,6 +4631,11 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, return 0; } +static bool IsOverloaded(const Sema::FunctionSet &Functions) { + return Functions.size() > 1 || + (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin())); +} + /// \brief Create a unary operation that may resolve to an overloaded /// operator. /// @@ -4716,15 +4677,14 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, } if (Input->isTypeDependent()) { - OverloadedFunctionDecl *Overloads - = OverloadedFunctionDecl::Create(Context, CurContext, OpName); + UnresolvedLookupExpr *Fn + = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, + 0, SourceRange(), OpName, OpLoc, + /*ADL*/ true, IsOverloaded(Functions)); for (FunctionSet::iterator Func = Functions.begin(), FuncEnd = Functions.end(); Func != FuncEnd; ++Func) - Overloads->addOverload(*Func); - - DeclRefExpr *Fn = new (Context) DeclRefExpr(Overloads, Context.OverloadTy, - OpLoc, false, false); + Fn->addDecl(*Func); input.release(); return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, @@ -4874,15 +4834,15 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, OpLoc)); } - OverloadedFunctionDecl *Overloads - = OverloadedFunctionDecl::Create(Context, CurContext, OpName); + UnresolvedLookupExpr *Fn + = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, + 0, SourceRange(), OpName, OpLoc, + /* ADL */ true, IsOverloaded(Functions)); + for (FunctionSet::iterator Func = Functions.begin(), FuncEnd = Functions.end(); Func != FuncEnd; ++Func) - Overloads->addOverload(*Func); - - DeclRefExpr *Fn = new (Context) DeclRefExpr(Overloads, Context.OverloadTy, - OpLoc, false, false); + Fn->addDecl(*Func); return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args, 2, @@ -5040,11 +5000,11 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // expression. if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) { - OverloadedFunctionDecl *Overloads - = OverloadedFunctionDecl::Create(Context, CurContext, OpName); - - DeclRefExpr *Fn = new (Context) DeclRefExpr(Overloads, Context.OverloadTy, - LLoc, false, false); + UnresolvedLookupExpr *Fn + = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, + 0, SourceRange(), OpName, LLoc, + /*ADL*/ true, /*Overloaded*/ false); + // Can't add any actual overloads yet Base.release(); Idx.release(); @@ -5169,51 +5129,63 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, SourceLocation RParenLoc) { // Dig out the member expression. This holds both the object // argument and the member function we're referring to. - MemberExpr *MemExpr = 0; - if (ParenExpr *ParenE = dyn_cast<ParenExpr>(MemExprE)) - MemExpr = dyn_cast<MemberExpr>(ParenE->getSubExpr()); - else - MemExpr = dyn_cast<MemberExpr>(MemExprE); - assert(MemExpr && "Building member call without member expression"); - + Expr *NakedMemExpr = MemExprE->IgnoreParens(); + // Extract the object argument. - Expr *ObjectArg = MemExpr->getBase(); + Expr *ObjectArg; + MemberExpr *MemExpr; CXXMethodDecl *Method = 0; - if (isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) || - isa<FunctionTemplateDecl>(MemExpr->getMemberDecl())) { + if (isa<MemberExpr>(NakedMemExpr)) { + MemExpr = cast<MemberExpr>(NakedMemExpr); + ObjectArg = MemExpr->getBase(); + Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl()); + } else { + UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr); + ObjectArg = UnresExpr->getBase(); + // Add overload candidates OverloadCandidateSet CandidateSet; - DeclarationName DeclName = MemExpr->getMemberDecl()->getDeclName(); - for (OverloadIterator Func(MemExpr->getMemberDecl()), FuncEnd; - Func != FuncEnd; ++Func) { - if ((Method = dyn_cast<CXXMethodDecl>(*Func))) { + for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(), + E = UnresExpr->decls_end(); I != E; ++I) { + + // TODO: note if we found something through a using declaration + NamedDecl *Func = (*I)->getUnderlyingDecl(); + + if ((Method = dyn_cast<CXXMethodDecl>(Func))) { // If explicit template arguments were provided, we can't call a // non-template member function. - if (MemExpr->hasExplicitTemplateArgumentList()) + if (UnresExpr->hasExplicitTemplateArgs()) continue; AddMethodCandidate(Method, ObjectArg, Args, NumArgs, CandidateSet, /*SuppressUserConversions=*/false); - } else - AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func), - MemExpr->hasExplicitTemplateArgumentList(), - MemExpr->getTemplateArgs(), - MemExpr->getNumTemplateArgs(), + } else { + // FIXME: avoid copy. + TemplateArgumentListInfo TemplateArgs; + if (UnresExpr->hasExplicitTemplateArgs()) + UnresExpr->copyTemplateArgumentsInto(TemplateArgs); + + AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func), + (UnresExpr->hasExplicitTemplateArgs() + ? &TemplateArgs : 0), ObjectArg, Args, NumArgs, CandidateSet, /*SuppressUsedConversions=*/false); + } } + DeclarationName DeclName = UnresExpr->getMemberName(); + OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, MemExpr->getLocStart(), Best)) { + switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) { case OR_Success: Method = cast<CXXMethodDecl>(Best->Function); break; case OR_No_Viable_Function: - Diag(MemExpr->getSourceRange().getBegin(), + Diag(UnresExpr->getMemberLoc(), diag::err_ovl_no_viable_member_function_in_call) << DeclName << MemExprE->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); @@ -5221,16 +5193,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, return true; case OR_Ambiguous: - Diag(MemExpr->getSourceRange().getBegin(), - diag::err_ovl_ambiguous_member_call) + Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call) << DeclName << MemExprE->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); // FIXME: Leaking incoming expressions! return true; case OR_Deleted: - Diag(MemExpr->getSourceRange().getBegin(), - diag::err_ovl_deleted_member_call) + Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call) << Best->Function->isDeleted() << DeclName << MemExprE->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); @@ -5238,9 +5208,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, return true; } - FixOverloadedFunctionReference(MemExpr, Method); - } else { - Method = dyn_cast<CXXMethodDecl>(MemExpr->getMemberDecl()); + MemExprE = FixOverloadedFunctionReference(MemExprE, Method); + MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens()); } assert(Method && "Member call to something that isn't a method?"); @@ -5329,21 +5298,17 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // accessible base class provided the function is not hidden // within T by another intervening declaration. // FIXME: Look in base classes for more conversion operators! - OverloadedFunctionDecl *Conversions + const UnresolvedSet *Conversions = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions(); - for (OverloadedFunctionDecl::function_iterator - Func = Conversions->function_begin(), - FuncEnd = Conversions->function_end(); - Func != FuncEnd; ++Func) { - CXXConversionDecl *Conv; - FunctionTemplateDecl *ConvTemplate; - GetFunctionAndTemplate(*Func, Conv, ConvTemplate); - + for (UnresolvedSet::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { // Skip over templated conversion functions; they aren't // surrogates. - if (ConvTemplate) + if (isa<FunctionTemplateDecl>(*I)) continue; + CXXConversionDecl *Conv = cast<CXXConversionDecl>(*I); + // Strip the reference type (if any) and then the pointer type (if // any) to get down to what might be a function type. QualType ConvType = Conv->getConversionType().getNonReferenceType(); @@ -5604,80 +5569,111 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { /// refer (possibly indirectly) to Fn. Returns the new expr. Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) { - Expr *NewExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn); - PE->setSubExpr(NewExpr); - PE->setType(NewExpr->getType()); - } else if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { - Expr *NewExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Fn); + Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn); + if (SubExpr == PE->getSubExpr()) + return PE->Retain(); + + return new (Context) ParenExpr(PE->getLParen(), PE->getRParen(), SubExpr); + } + + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { + Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Fn); assert(Context.hasSameType(ICE->getSubExpr()->getType(), - NewExpr->getType()) && + SubExpr->getType()) && "Implicit cast type cannot be determined from overload"); - ICE->setSubExpr(NewExpr); - } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) { + if (SubExpr == ICE->getSubExpr()) + return ICE->Retain(); + + return new (Context) ImplicitCastExpr(ICE->getType(), + ICE->getCastKind(), + SubExpr, + ICE->isLvalueCast()); + } + + if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) { assert(UnOp->getOpcode() == UnaryOperator::AddrOf && "Can only take the address of an overloaded function"); if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) { if (Method->isStatic()) { // Do nothing: static member functions aren't any different // from non-member functions. - } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr())) { - if (DRE->getQualifier()) { - // We have taken the address of a pointer to member - // function. Perform the computation here so that we get the - // appropriate pointer to member type. - DRE->setDecl(Fn); - DRE->setType(Fn->getType()); - QualType ClassType - = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext())); - E->setType(Context.getMemberPointerType(Fn->getType(), - ClassType.getTypePtr())); - return E; - } + } else { + // Fix the sub expression, which really has to be an + // UnresolvedLookupExpr holding an overloaded member function + // or template. + Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn); + if (SubExpr == UnOp->getSubExpr()) + return UnOp->Retain(); + + assert(isa<DeclRefExpr>(SubExpr) + && "fixed to something other than a decl ref"); + assert(cast<DeclRefExpr>(SubExpr)->getQualifier() + && "fixed to a member ref with no nested name qualifier"); + + // We have taken the address of a pointer to member + // function. Perform the computation here so that we get the + // appropriate pointer to member type. + QualType ClassType + = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext())); + QualType MemPtrType + = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr()); + + return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf, + MemPtrType, UnOp->getOperatorLoc()); } - // FIXME: TemplateIdRefExpr referring to a member function template - // specialization! } - Expr *NewExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn); - UnOp->setSubExpr(NewExpr); - UnOp->setType(Context.getPointerType(NewExpr->getType())); + Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn); + if (SubExpr == UnOp->getSubExpr()) + return UnOp->Retain(); - return UnOp; - } else if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) { - assert((isa<OverloadedFunctionDecl>(DR->getDecl()) || - isa<FunctionTemplateDecl>(DR->getDecl()) || - isa<FunctionDecl>(DR->getDecl())) && - "Expected function or function template"); - DR->setDecl(Fn); - E->setType(Fn->getType()); - } else if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) { - MemExpr->setMemberDecl(Fn); - E->setType(Fn->getType()); - } else if (TemplateIdRefExpr *TID = dyn_cast<TemplateIdRefExpr>(E)) { - E = DeclRefExpr::Create(Context, - TID->getQualifier(), TID->getQualifierRange(), - Fn, TID->getTemplateNameLoc(), - true, - TID->getLAngleLoc(), - TID->getTemplateArgs(), - TID->getNumTemplateArgs(), - TID->getRAngleLoc(), - Fn->getType(), - /*FIXME?*/false, /*FIXME?*/false); - - // FIXME: Don't destroy TID here, since we need its template arguments - // to survive. - // TID->Destroy(Context); - } else if (isa<UnresolvedFunctionNameExpr>(E)) { - return DeclRefExpr::Create(Context, - /*Qualifier=*/0, - /*QualifierRange=*/SourceRange(), - Fn, E->getLocStart(), - Fn->getType(), false, false); - } else { - assert(false && "Invalid reference to overloaded function"); + return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf, + Context.getPointerType(SubExpr->getType()), + UnOp->getOperatorLoc()); + } + + if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) { + if (ULE->hasExplicitTemplateArgs()) { + // FIXME: avoid copy. + TemplateArgumentListInfo TemplateArgs; + if (ULE->hasExplicitTemplateArgs()) + ULE->copyTemplateArgumentsInto(TemplateArgs); + + return DeclRefExpr::Create(Context, + ULE->getQualifier(), + ULE->getQualifierRange(), + Fn, + ULE->getNameLoc(), + Fn->getType(), + &TemplateArgs); + } + + return DeclRefExpr::Create(Context, + ULE->getQualifier(), + ULE->getQualifierRange(), + Fn, + ULE->getNameLoc(), + Fn->getType()); + } + + if (UnresolvedMemberExpr *MemExpr = dyn_cast<UnresolvedMemberExpr>(E)) { + // FIXME: avoid copy. + TemplateArgumentListInfo TemplateArgs; + if (MemExpr->hasExplicitTemplateArgs()) + MemExpr->copyTemplateArgumentsInto(TemplateArgs); + + return MemberExpr::Create(Context, MemExpr->getBase()->Retain(), + MemExpr->isArrow(), + MemExpr->getQualifier(), + MemExpr->getQualifierRange(), + Fn, + MemExpr->getMemberLoc(), + (MemExpr->hasExplicitTemplateArgs() + ? &TemplateArgs : 0), + Fn->getType()); } - return E; + assert(false && "Invalid reference to overloaded function"); + return E->Retain(); } } // end namespace clang diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index d0f214f..de67a5f 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -15,9 +15,11 @@ #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtCXX.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -59,6 +61,15 @@ Sema::OwningStmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, return Owned(new (Context) DeclStmt(DG, StartLoc, EndLoc)); } +void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) { + DeclGroupRef DG = dg.getAsVal<DeclGroupRef>(); + + // If we have an invalid decl, just return. + if (DG.isNull() || !DG.isSingleDecl()) return; + // suppress any potential 'unused variable' warning. + DG.getSingleDecl()->setUsed(); +} + void Sema::DiagnoseUnusedExprResult(const Stmt *S) { const Expr *E = dyn_cast_or_null<Expr>(S); if (!E) @@ -225,16 +236,24 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, } Action::OwningStmtResult -Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, +Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, DeclPtrTy CondVar, StmtArg ThenVal, SourceLocation ElseLoc, StmtArg ElseVal) { OwningExprResult CondResult(CondVal.release()); - Expr *condExpr = CondResult.takeAs<Expr>(); - - assert(condExpr && "ActOnIfStmt(): missing expression"); - if (CheckBooleanCondition(condExpr, IfLoc)) { - CondResult = condExpr; + VarDecl *ConditionVar = 0; + if (CondVar.get()) { + ConditionVar = CondVar.getAs<VarDecl>(); + CondResult = CheckConditionVariable(ConditionVar); + if (CondResult.isInvalid()) + return StmtError(); + } + Expr *ConditionExpr = CondResult.takeAs<Expr>(); + if (!ConditionExpr) + return StmtError(); + + if (CheckBooleanCondition(ConditionExpr, IfLoc)) { + CondResult = ConditionExpr; return StmtError(); } @@ -254,41 +273,23 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, DiagnoseUnusedExprResult(elseStmt); CondResult.release(); - return Owned(new (Context) IfStmt(IfLoc, condExpr, thenStmt, - ElseLoc, elseStmt)); + return Owned(new (Context) IfStmt(IfLoc, ConditionVar, ConditionExpr, + thenStmt, ElseLoc, elseStmt)); } Action::OwningStmtResult -Sema::ActOnStartOfSwitchStmt(ExprArg cond) { - Expr *Cond = cond.takeAs<Expr>(); - - if (getLangOptions().CPlusPlus) { - // C++ 6.4.2.p2: - // The condition shall be of integral type, enumeration type, or of a class - // type for which a single conversion function to integral or enumeration - // type exists (12.3). If the condition is of class type, the condition is - // converted by calling that conversion function, and the result of the - // conversion is used in place of the original condition for the remainder - // of this section. Integral promotions are performed. - if (!Cond->isTypeDependent()) { - QualType Ty = Cond->getType(); - - // FIXME: Handle class types. - - // If the type is wrong a diagnostic will be emitted later at - // ActOnFinishSwitchStmt. - if (Ty->isIntegralType() || Ty->isEnumeralType()) { - // Integral promotions are performed. - // FIXME: Integral promotions for C++ are not complete. - UsualUnaryConversions(Cond); - } - } - } else { - // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr. - UsualUnaryConversions(Cond); +Sema::ActOnStartOfSwitchStmt(FullExprArg cond, DeclPtrTy CondVar) { + OwningExprResult CondResult(cond.release()); + + VarDecl *ConditionVar = 0; + if (CondVar.get()) { + ConditionVar = CondVar.getAs<VarDecl>(); + CondResult = CheckConditionVariable(ConditionVar); + if (CondResult.isInvalid()) + return StmtError(); } - - SwitchStmt *SS = new (Context) SwitchStmt(Cond); + SwitchStmt *SS = new (Context) SwitchStmt(ConditionVar, + CondResult.takeAs<Expr>()); getSwitchStack().push_back(SS); return Owned(SS); } @@ -383,6 +384,103 @@ static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) { return expr->getType(); } +/// \brief Check (and possibly convert) the condition in a switch +/// statement in C++. +static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc, + Expr *&CondExpr) { + if (CondExpr->isTypeDependent()) + return false; + + QualType CondType = CondExpr->getType(); + + // C++ 6.4.2.p2: + // The condition shall be of integral type, enumeration type, or of a class + // type for which a single conversion function to integral or enumeration + // type exists (12.3). If the condition is of class type, the condition is + // converted by calling that conversion function, and the result of the + // conversion is used in place of the original condition for the remainder + // of this section. Integral promotions are performed. + + // Make sure that the condition expression has a complete type, + // otherwise we'll never find any conversions. + if (S.RequireCompleteType(SwitchLoc, CondType, + PDiag(diag::err_switch_incomplete_class_type) + << CondExpr->getSourceRange())) + return true; + + llvm::SmallVector<CXXConversionDecl *, 4> ViableConversions; + llvm::SmallVector<CXXConversionDecl *, 4> ExplicitConversions; + if (const RecordType *RecordTy = CondType->getAs<RecordType>()) { + const UnresolvedSet *Conversions + = cast<CXXRecordDecl>(RecordTy->getDecl()) + ->getVisibleConversionFunctions(); + for (UnresolvedSet::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(*I)) + if (Conversion->getConversionType().getNonReferenceType() + ->isIntegralType()) { + if (Conversion->isExplicit()) + ExplicitConversions.push_back(Conversion); + else + ViableConversions.push_back(Conversion); + } + } + + switch (ViableConversions.size()) { + case 0: + if (ExplicitConversions.size() == 1) { + // The user probably meant to invoke the given explicit + // conversion; use it. + QualType ConvTy + = ExplicitConversions[0]->getConversionType() + .getNonReferenceType(); + std::string TypeStr; + ConvTy.getAsStringInternal(TypeStr, S.Context.PrintingPolicy); + + S.Diag(SwitchLoc, diag::err_switch_explicit_conversion) + << CondType << ConvTy << CondExpr->getSourceRange() + << CodeModificationHint::CreateInsertion(CondExpr->getLocStart(), + "static_cast<" + TypeStr + ">(") + << CodeModificationHint::CreateInsertion( + S.PP.getLocForEndOfToken(CondExpr->getLocEnd()), + ")"); + S.Diag(ExplicitConversions[0]->getLocation(), + diag::note_switch_conversion) + << ConvTy->isEnumeralType() << ConvTy; + + // If we aren't in a SFINAE context, build a call to the + // explicit conversion function. + if (S.isSFINAEContext()) + return true; + + CondExpr = S.BuildCXXMemberCallExpr(CondExpr, ExplicitConversions[0]); + } + + // We'll complain below about a non-integral condition type. + break; + + case 1: + // Apply this conversion. + CondExpr = S.BuildCXXMemberCallExpr(CondExpr, ViableConversions[0]); + break; + + default: + S.Diag(SwitchLoc, diag::err_switch_multiple_conversions) + << CondType << CondExpr->getSourceRange(); + for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { + QualType ConvTy + = ViableConversions[I]->getConversionType().getNonReferenceType(); + S.Diag(ViableConversions[I]->getLocation(), + diag::note_switch_conversion) + << ConvTy->isEnumeralType() << ConvTy; + } + return true; + } + } + + return false; +} + Action::OwningStmtResult Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, StmtArg Body) { @@ -394,8 +492,23 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, SS->setBody(BodyStmt, SwitchLoc); getSwitchStack().pop_back(); + if (SS->getCond() == 0) { + SS->Destroy(Context); + return StmtError(); + } + Expr *CondExpr = SS->getCond(); + QualType CondTypeBeforePromotion = + GetTypeBeforeIntegralPromotion(CondExpr); + + if (getLangOptions().CPlusPlus && + CheckCXXSwitchCondition(*this, SwitchLoc, CondExpr)) + return StmtError(); + + // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr. + UsualUnaryConversions(CondExpr); QualType CondType = CondExpr->getType(); + SS->setCond(CondExpr); // C++ 6.4.2.p2: // Integral promotions are performed (on the switch condition). @@ -404,9 +517,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, // type (before the promotion) doesn't make sense, even when it can // be represented by the promoted type. Therefore we need to find // the pre-promotion type of the switch condition. - QualType CondTypeBeforePromotion = - GetTypeBeforeIntegralPromotion(CondExpr); - if (!CondExpr->isTypeDependent()) { if (!CondType->isIntegerType()) { // C99 6.8.4.2p1 Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer) @@ -614,21 +724,32 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, } Action::OwningStmtResult -Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, StmtArg Body) { - ExprArg CondArg(Cond.release()); - Expr *condExpr = CondArg.takeAs<Expr>(); - assert(condExpr && "ActOnWhileStmt(): missing expression"); - - if (CheckBooleanCondition(condExpr, WhileLoc)) { - CondArg = condExpr; +Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, + DeclPtrTy CondVar, StmtArg Body) { + OwningExprResult CondResult(Cond.release()); + + VarDecl *ConditionVar = 0; + if (CondVar.get()) { + ConditionVar = CondVar.getAs<VarDecl>(); + CondResult = CheckConditionVariable(ConditionVar); + if (CondResult.isInvalid()) + return StmtError(); + } + Expr *ConditionExpr = CondResult.takeAs<Expr>(); + if (!ConditionExpr) + return StmtError(); + + if (CheckBooleanCondition(ConditionExpr, WhileLoc)) { + CondResult = ConditionExpr; return StmtError(); } Stmt *bodyStmt = Body.takeAs<Stmt>(); DiagnoseUnusedExprResult(bodyStmt); - CondArg.release(); - return Owned(new (Context) WhileStmt(condExpr, bodyStmt, WhileLoc)); + CondResult.release(); + return Owned(new (Context) WhileStmt(ConditionVar, ConditionExpr, bodyStmt, + WhileLoc)); } Action::OwningStmtResult @@ -653,12 +774,10 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, StmtArg Body, Action::OwningStmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - StmtArg first, ExprArg second, ExprArg third, + StmtArg first, FullExprArg second, DeclPtrTy secondVar, + FullExprArg third, SourceLocation RParenLoc, StmtArg body) { Stmt *First = static_cast<Stmt*>(first.get()); - Expr *Second = second.takeAs<Expr>(); - Expr *Third = static_cast<Expr*>(third.get()); - Stmt *Body = static_cast<Stmt*>(body.get()); if (!getLangOptions().CPlusPlus) { if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) { @@ -676,20 +795,33 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, } } } + + OwningExprResult SecondResult(second.release()); + VarDecl *ConditionVar = 0; + if (secondVar.get()) { + ConditionVar = secondVar.getAs<VarDecl>(); + SecondResult = CheckConditionVariable(ConditionVar); + if (SecondResult.isInvalid()) + return StmtError(); + } + + Expr *Second = SecondResult.takeAs<Expr>(); if (Second && CheckBooleanCondition(Second, ForLoc)) { - second = Second; + SecondResult = Second; return StmtError(); } + Expr *Third = third.release().takeAs<Expr>(); + Stmt *Body = static_cast<Stmt*>(body.get()); + DiagnoseUnusedExprResult(First); DiagnoseUnusedExprResult(Third); DiagnoseUnusedExprResult(Body); first.release(); - third.release(); body.release(); - return Owned(new (Context) ForStmt(First, Second, Third, Body, ForLoc, - LParenLoc, RParenLoc)); + return Owned(new (Context) ForStmt(First, Second, ConditionVar, Third, Body, + ForLoc, LParenLoc, RParenLoc)); } Action::OwningStmtResult diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 31cd300..f47577e 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -20,7 +20,6 @@ #include "clang/Parse/Template.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/PartialDiagnostic.h" -#include "llvm/Support/Compiler.h" #include "llvm/ADT/StringExtras.h" using namespace clang; @@ -59,44 +58,20 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context, NamedDecl *D) { return 0; } - OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D); - if (!Ovl) - return 0; - - for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(), - FEnd = Ovl->function_end(); - F != FEnd; ++F) { - if (FunctionTemplateDecl *FuncTmpl = dyn_cast<FunctionTemplateDecl>(*F)) { - // We've found a function template. Determine whether there are - // any other function templates we need to bundle together in an - // OverloadedFunctionDecl - for (++F; F != FEnd; ++F) { - if (isa<FunctionTemplateDecl>(*F)) - break; - } - - if (F != FEnd) { - // Build an overloaded function decl containing only the - // function templates in Ovl. - OverloadedFunctionDecl *OvlTemplate - = OverloadedFunctionDecl::Create(Context, - Ovl->getDeclContext(), - Ovl->getDeclName()); - OvlTemplate->addOverload(FuncTmpl); - OvlTemplate->addOverload(*F); - for (++F; F != FEnd; ++F) { - if (isa<FunctionTemplateDecl>(*F)) - OvlTemplate->addOverload(*F); - } - - return OvlTemplate; - } + return 0; +} - return FuncTmpl; - } +static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) { + LookupResult::Filter filter = R.makeFilter(); + while (filter.hasNext()) { + NamedDecl *Orig = filter.next(); + NamedDecl *Repl = isAcceptableTemplateName(C, Orig->getUnderlyingDecl()); + if (!Repl) + filter.erase(); + else if (Repl != Orig) + filter.replace(Repl); } - - return 0; + filter.done(); } TemplateNameKind Sema::isTemplateName(Scope *S, @@ -117,18 +92,65 @@ TemplateNameKind Sema::isTemplateName(Scope *S, Name.OperatorFunctionId.Operator); break; + case UnqualifiedId::IK_LiteralOperatorId: + TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier); + break; + default: return TNK_Non_template; } - + + QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr); + + LookupResult R(*this, TName, SourceLocation(), LookupOrdinaryName); + R.suppressDiagnostics(); + LookupTemplateName(R, S, SS, ObjectType, EnteringContext); + if (R.empty()) + return TNK_Non_template; + + NamedDecl *Template = R.getAsSingleDecl(Context); + + if (SS.isSet() && !SS.isInvalid()) { + NestedNameSpecifier *Qualifier + = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + if (OverloadedFunctionDecl *Ovl + = dyn_cast<OverloadedFunctionDecl>(Template)) + TemplateResult + = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, false, + Ovl)); + else + TemplateResult + = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, false, + cast<TemplateDecl>(Template))); + } else if (OverloadedFunctionDecl *Ovl + = dyn_cast<OverloadedFunctionDecl>(Template)) { + TemplateResult = TemplateTy::make(TemplateName(Ovl)); + } else { + TemplateResult = TemplateTy::make( + TemplateName(cast<TemplateDecl>(Template))); + } + + if (isa<ClassTemplateDecl>(Template) || + isa<TemplateTemplateParmDecl>(Template)) + return TNK_Type_template; + + assert((isa<FunctionTemplateDecl>(Template) || + isa<OverloadedFunctionDecl>(Template)) && + "Unhandled template kind in Sema::isTemplateName"); + return TNK_Function_template; +} + +void Sema::LookupTemplateName(LookupResult &Found, + Scope *S, const CXXScopeSpec &SS, + QualType ObjectType, + bool EnteringContext) { // Determine where to perform name lookup DeclContext *LookupCtx = 0; bool isDependent = false; - if (ObjectTypePtr) { + if (!ObjectType.isNull()) { // This nested-name-specifier occurs in a member access expression, e.g., // x->B::f, and we are looking into the type of the object. assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); - QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr); LookupCtx = computeDeclContext(ObjectType); isDependent = ObjectType->isDependentType(); assert((isDependent || !ObjectType->isIncompleteType()) && @@ -141,10 +163,9 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // The declaration context must be complete. if (LookupCtx && RequireCompleteDeclContext(SS)) - return TNK_Non_template; + return; } - LookupResult Found(*this, TName, SourceLocation(), LookupOrdinaryName); bool ObjectTypeSearchedInScope = false; if (LookupCtx) { // Perform "qualified" name lookup into the declaration context we @@ -153,7 +174,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // nested-name-specifier. LookupQualifiedName(Found, LookupCtx); - if (ObjectTypePtr && Found.empty()) { + if (!ObjectType.isNull() && Found.empty()) { // C++ [basic.lookup.classref]p1: // In a class member access expression (5.2.5), if the . or -> token is // immediately followed by an identifier followed by a <, the @@ -166,12 +187,12 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // // FIXME: When we're instantiating a template, do we actually have to // look in the scope of the template? Seems fishy... - LookupName(Found, S); + if (S) LookupName(Found, S); ObjectTypeSearchedInScope = true; } } else if (isDependent) { // We cannot look into a dependent object type or - return TNK_Non_template; + return; } else { // Perform unqualified name lookup in the current scope. LookupName(Found, S); @@ -181,27 +202,26 @@ TemplateNameKind Sema::isTemplateName(Scope *S, assert(!Found.isAmbiguous() && "Cannot handle template name-lookup ambiguities"); - NamedDecl *Template - = isAcceptableTemplateName(Context, Found.getAsSingleDecl(Context)); - if (!Template) - return TNK_Non_template; + FilterAcceptableTemplateNames(Context, Found); + if (Found.empty()) + return; - if (ObjectTypePtr && !ObjectTypeSearchedInScope) { + if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope) { // C++ [basic.lookup.classref]p1: // [...] If the lookup in the class of the object expression finds a // template, the name is also looked up in the context of the entire // postfix-expression and [...] // - LookupResult FoundOuter(*this, TName, SourceLocation(), LookupOrdinaryName); + LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(), + LookupOrdinaryName); LookupName(FoundOuter, S); + FilterAcceptableTemplateNames(Context, FoundOuter); // FIXME: Handle ambiguities in this lookup better - NamedDecl *OuterTemplate - = isAcceptableTemplateName(Context, FoundOuter.getAsSingleDecl(Context)); - if (!OuterTemplate) { + if (FoundOuter.empty()) { // - if the name is not found, the name found in the class of the // object expression is used, otherwise - } else if (!isa<ClassTemplateDecl>(OuterTemplate)) { + } else if (!FoundOuter.getAsSingle<ClassTemplateDecl>()) { // - if the name is found in the context of the entire // postfix-expression and does not name a class template, the name // found in the class of the object expression is used, otherwise @@ -209,49 +229,165 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // - if the name found is a class template, it must refer to the same // entity as the one found in the class of the object expression, // otherwise the program is ill-formed. - if (OuterTemplate->getCanonicalDecl() != Template->getCanonicalDecl()) { - Diag(Name.getSourceRange().getBegin(), + if (!Found.isSingleResult() || + Found.getFoundDecl()->getCanonicalDecl() + != FoundOuter.getFoundDecl()->getCanonicalDecl()) { + Diag(Found.getNameLoc(), diag::err_nested_name_member_ref_lookup_ambiguous) - << TName - << Name.getSourceRange(); - Diag(Template->getLocation(), diag::note_ambig_member_ref_object_type) - << QualType::getFromOpaquePtr(ObjectTypePtr); - Diag(OuterTemplate->getLocation(), diag::note_ambig_member_ref_scope); + << Found.getLookupName(); + Diag(Found.getRepresentativeDecl()->getLocation(), + diag::note_ambig_member_ref_object_type) + << ObjectType; + Diag(FoundOuter.getFoundDecl()->getLocation(), + diag::note_ambig_member_ref_scope); // Recover by taking the template that we found in the object // expression's type. } } } +} - if (SS.isSet() && !SS.isInvalid()) { - NestedNameSpecifier *Qualifier - = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - if (OverloadedFunctionDecl *Ovl - = dyn_cast<OverloadedFunctionDecl>(Template)) - TemplateResult - = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, false, - Ovl)); - else - TemplateResult - = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, false, - cast<TemplateDecl>(Template))); - } else if (OverloadedFunctionDecl *Ovl - = dyn_cast<OverloadedFunctionDecl>(Template)) { - TemplateResult = TemplateTy::make(TemplateName(Ovl)); - } else { - TemplateResult = TemplateTy::make( - TemplateName(cast<TemplateDecl>(Template))); +/// Constructs a full type for the given nested-name-specifier. +static QualType GetTypeForQualifier(ASTContext &Context, + NestedNameSpecifier *Qualifier) { + // Three possibilities: + + // 1. A namespace (global or not). + assert(!Qualifier->getAsNamespace() && "can't construct type for namespace"); + + // 2. A type (templated or not). + Type *Ty = Qualifier->getAsType(); + if (Ty) return QualType(Ty, 0); + + // 3. A dependent identifier. + assert(Qualifier->getAsIdentifier()); + return Context.getTypenameType(Qualifier->getPrefix(), + Qualifier->getAsIdentifier()); +} + +static bool HasDependentTypeAsBase(ASTContext &Context, + CXXRecordDecl *Record, + CanQualType T) { + for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(), + E = Record->bases_end(); I != E; ++I) { + CanQualType BaseT = Context.getCanonicalType((*I).getType()); + if (BaseT == T) + return true; + + // We have to recurse here to cover some really bizarre cases. + // Obviously, we can only have the dependent type as an indirect + // base class through a dependent base class, and usually it's + // impossible to know which instantiation a dependent base class + // will have. But! If we're actually *inside* the dependent base + // class, then we know its instantiation and can therefore be + // reasonably expected to look into it. + + // template <class T> class A : Base<T> { + // class Inner : A<T> { + // void foo() { + // Base<T>::foo(); // statically known to be an implicit member + // reference + // } + // }; + // }; + + CanQual<RecordType> RT = BaseT->getAs<RecordType>(); + + // Base might be a dependent member type, in which case we + // obviously can't look into it. + if (!RT) continue; + + CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(RT->getDecl()); + if (BaseRecord->isDefinition() && + HasDependentTypeAsBase(Context, BaseRecord, T)) + return true; } - if (isa<ClassTemplateDecl>(Template) || - isa<TemplateTemplateParmDecl>(Template)) - return TNK_Type_template; + return false; +} - assert((isa<FunctionTemplateDecl>(Template) || - isa<OverloadedFunctionDecl>(Template)) && - "Unhandled template kind in Sema::isTemplateName"); - return TNK_Function_template; +/// Checks whether the given dependent nested-name specifier +/// introduces an implicit member reference. This is only true if the +/// nested-name specifier names a type identical to one of the current +/// instance method's context's (possibly indirect) base classes. +static bool IsImplicitDependentMemberReference(Sema &SemaRef, + NestedNameSpecifier *Qualifier, + QualType &ThisType) { + // If the context isn't a C++ method, then it isn't an implicit + // member reference. + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(SemaRef.CurContext); + if (!MD || MD->isStatic()) + return false; + + ASTContext &Context = SemaRef.Context; + + // We want to check whether the method's context is known to inherit + // from the type named by the nested name specifier. The trivial + // case here is: + // template <class T> class Base { ... }; + // template <class T> class Derived : Base<T> { + // void foo() { + // Base<T>::foo(); + // } + // }; + + QualType QT = GetTypeForQualifier(Context, Qualifier); + CanQualType T = Context.getCanonicalType(QT); + + // And now, just walk the non-dependent type hierarchy, trying to + // find the given type as a literal base class. + CXXRecordDecl *Record = cast<CXXRecordDecl>(MD->getParent()); + if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T || + HasDependentTypeAsBase(Context, Record, T)) { + ThisType = MD->getThisType(Context); + return true; + } + + return false; +} + +/// ActOnDependentIdExpression - Handle a dependent declaration name +/// that was just parsed. +Sema::OwningExprResult +Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + bool CheckForImplicitMember, + const TemplateArgumentListInfo *TemplateArgs) { + NestedNameSpecifier *Qualifier + = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); + + QualType ThisType; + if (CheckForImplicitMember && + IsImplicitDependentMemberReference(*this, Qualifier, ThisType)) { + Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType); + + // Since the 'this' expression is synthesized, we don't need to + // perform the double-lookup check. + NamedDecl *FirstQualifierInScope = 0; + + return Owned(CXXDependentScopeMemberExpr::Create(Context, This, true, + /*Op*/ SourceLocation(), + Qualifier, SS.getRange(), + FirstQualifierInScope, + Name, NameLoc, + TemplateArgs)); + } + + return BuildDependentDeclRefExpr(SS, Name, NameLoc, TemplateArgs); +} + +Sema::OwningExprResult +Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs) { + return Owned(DependentScopeDeclRefExpr::Create(Context, + static_cast<NestedNameSpecifier*>(SS.getScopeRep()), + SS.getRange(), + Name, NameLoc, + TemplateArgs)); } /// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining @@ -317,12 +453,11 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, /// \brief Translates template arguments as provided by the parser /// into template arguments used by semantic analysis. -void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, - llvm::SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) { - TemplateArgs.reserve(TemplateArgsIn.size()); - +void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn, + TemplateArgumentListInfo &TemplateArgs) { for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I) - TemplateArgs.push_back(translateTemplateArgument(*this, TemplateArgsIn[I])); + TemplateArgs.addArgument(translateTemplateArgument(*this, + TemplateArgsIn[I])); } /// ActOnTypeParameter - Called when a C++ template type parameter @@ -595,7 +730,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth, DeclPtrTy *Params, unsigned NumParams, SourceLocation RAngleLoc) { if (ExportLoc.isValid()) - Diag(ExportLoc, diag::note_template_export_unsupported); + Diag(ExportLoc, diag::warn_template_export_unsupported); return TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc, (NamedDecl**)Params, NumParams, @@ -756,7 +891,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // merging in the template parameter list from the previous class // template declaration. if (CheckTemplateParameterList(TemplateParams, - PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0)) + PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0, + TPC_ClassTemplate)) Invalid = true; // FIXME: If we had a scope specifier, we better have a previous template @@ -837,6 +973,55 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, return DeclPtrTy::make(NewTemplate); } +/// \brief Diagnose the presence of a default template argument on a +/// template parameter, which is ill-formed in certain contexts. +/// +/// \returns true if the default template argument should be dropped. +static bool DiagnoseDefaultTemplateArgument(Sema &S, + Sema::TemplateParamListContext TPC, + SourceLocation ParamLoc, + SourceRange DefArgRange) { + switch (TPC) { + case Sema::TPC_ClassTemplate: + return false; + + case Sema::TPC_FunctionTemplate: + // C++ [temp.param]p9: + // A default template-argument shall not be specified in a + // function template declaration or a function template + // definition [...] + // (This sentence is not in C++0x, per DR226). + if (!S.getLangOptions().CPlusPlus0x) + S.Diag(ParamLoc, + diag::err_template_parameter_default_in_function_template) + << DefArgRange; + return false; + + case Sema::TPC_ClassTemplateMember: + // C++0x [temp.param]p9: + // A default template-argument shall not be specified in the + // template-parameter-lists of the definition of a member of a + // class template that appears outside of the member's class. + S.Diag(ParamLoc, diag::err_template_parameter_default_template_member) + << DefArgRange; + return true; + + case Sema::TPC_FriendFunctionTemplate: + // C++ [temp.param]p9: + // A default template-argument shall not be specified in a + // friend template declaration. + S.Diag(ParamLoc, diag::err_template_parameter_default_friend_template) + << DefArgRange; + return true; + + // FIXME: C++0x [temp.param]p9 allows default template-arguments + // for friend function templates if there is only a single + // declaration (and it is a definition). Strange! + } + + return false; +} + /// \brief Checks the validity of a template parameter list, possibly /// considering the template parameter list from a previous /// declaration. @@ -855,9 +1040,13 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, /// arguments will be merged from the old template parameter list to /// the new template parameter list. /// +/// \param TPC Describes the context in which we are checking the given +/// template parameter list. +/// /// \returns true if an error occurred, false otherwise. bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, - TemplateParameterList *OldParams) { + TemplateParameterList *OldParams, + TemplateParamListContext TPC) { bool Invalid = false; // C++ [temp.param]p10: @@ -897,9 +1086,17 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, Invalid = true; } - // Merge default arguments for template type parameters. if (TemplateTypeParmDecl *NewTypeParm = dyn_cast<TemplateTypeParmDecl>(*NewParam)) { + // Check the presence of a default argument here. + if (NewTypeParm->hasDefaultArgument() && + DiagnoseDefaultTemplateArgument(*this, TPC, + NewTypeParm->getLocation(), + NewTypeParm->getDefaultArgumentInfo()->getTypeLoc() + .getFullSourceRange())) + NewTypeParm->removeDefaultArgument(); + + // Merge default arguments for template type parameters. TemplateTypeParmDecl *OldTypeParm = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : 0; @@ -929,6 +1126,15 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, MissingDefaultArg = true; } else if (NonTypeTemplateParmDecl *NewNonTypeParm = dyn_cast<NonTypeTemplateParmDecl>(*NewParam)) { + // Check the presence of a default argument here. + if (NewNonTypeParm->hasDefaultArgument() && + DiagnoseDefaultTemplateArgument(*this, TPC, + NewNonTypeParm->getLocation(), + NewNonTypeParm->getDefaultArgument()->getSourceRange())) { + NewNonTypeParm->getDefaultArgument()->Destroy(Context); + NewNonTypeParm->setDefaultArgument(0); + } + // Merge default arguments for non-type template parameters NonTypeTemplateParmDecl *OldNonTypeParm = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : 0; @@ -955,9 +1161,16 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (SawDefaultArgument) MissingDefaultArg = true; } else { - // Merge default arguments for template template parameters + // Check the presence of a default argument here. TemplateTemplateParmDecl *NewTemplateParm = cast<TemplateTemplateParmDecl>(*NewParam); + if (NewTemplateParm->hasDefaultArgument() && + DiagnoseDefaultTemplateArgument(*this, TPC, + NewTemplateParm->getLocation(), + NewTemplateParm->getDefaultArgument().getSourceRange())) + NewTemplateParm->setDefaultArgument(TemplateArgumentLoc()); + + // Merge default arguments for template template parameters TemplateTemplateParmDecl *OldTemplateParm = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0; if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() && @@ -1049,6 +1262,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // template-ids will match up with the template parameter lists. llvm::SmallVector<const TemplateSpecializationType *, 4> TemplateIdsInSpecifier; + llvm::SmallVector<ClassTemplateSpecializationDecl *, 4> + ExplicitSpecializationsInSpecifier; for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep(); NNS; NNS = NNS->getPrefix()) { if (const TemplateSpecializationType *SpecType @@ -1062,10 +1277,10 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, = cast<ClassTemplateSpecializationDecl>(Record->getDecl()); // If the nested name specifier refers to an explicit specialization, // we don't need a template<> header. - // FIXME: revisit this approach once we cope with specializations - // properly. - if (SpecDecl->getSpecializationKind() == TSK_ExplicitSpecialization) + if (SpecDecl->getSpecializationKind() == TSK_ExplicitSpecialization) { + ExplicitSpecializationsInSpecifier.push_back(SpecDecl); continue; + } } TemplateIdsInSpecifier.push_back(SpecType); @@ -1128,6 +1343,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, ExpectedTemplateParams, true, TPL_TemplateMatch); } + + CheckTemplateParameterList(ParamLists[Idx], 0, TPC_ClassTemplateMember); } else if (ParamLists[Idx]->size() > 0) Diag(ParamLists[Idx]->getTemplateLoc(), diag::err_template_param_list_matches_nontemplate) @@ -1146,10 +1363,20 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // If there were too many template parameter lists, complain about that now. if (Idx != NumParamLists - 1) { while (Idx < NumParamLists - 1) { + bool isExplicitSpecHeader = ParamLists[Idx]->size() == 0; Diag(ParamLists[Idx]->getTemplateLoc(), - diag::err_template_spec_extra_headers) + isExplicitSpecHeader? diag::warn_template_spec_extra_headers + : diag::err_template_spec_extra_headers) << SourceRange(ParamLists[Idx]->getTemplateLoc(), ParamLists[Idx]->getRAngleLoc()); + + if (isExplicitSpecHeader && !ExplicitSpecializationsInSpecifier.empty()) { + Diag(ExplicitSpecializationsInSpecifier.back()->getLocation(), + diag::note_explicit_template_spec_does_not_need_header) + << ExplicitSpecializationsInSpecifier.back(); + ExplicitSpecializationsInSpecifier.pop_back(); + } + ++Idx; } } @@ -1161,24 +1388,19 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, QualType Sema::CheckTemplateIdType(TemplateName Name, SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc) { + const TemplateArgumentListInfo &TemplateArgs) { TemplateDecl *Template = Name.getAsTemplateDecl(); if (!Template) { // The template name does not resolve to a template, so we just // build a dependent template-id type. - return Context.getTemplateSpecializationType(Name, TemplateArgs, - NumTemplateArgs); + return Context.getTemplateSpecializationType(Name, TemplateArgs); } // Check that the template argument list is well-formed for this // template. TemplateArgumentListBuilder Converted(Template->getTemplateParameters(), - NumTemplateArgs); - if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc, - TemplateArgs, NumTemplateArgs, RAngleLoc, + TemplateArgs.size()); + if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs, false, Converted)) return QualType(); @@ -1190,8 +1412,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, if (Name.isDependent() || TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs, - NumTemplateArgs)) { + TemplateArgs)) { // This class template specialization is a dependent // type. Therefore, its canonical type is another class template // specialization type that contains all of the converted @@ -1240,8 +1461,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Build the fully-sugared type for this class template // specialization, which refers back to the class template // specialization we created or found. - return Context.getTemplateSpecializationType(Name, TemplateArgs, - NumTemplateArgs, CanonType); + return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType); } Action::TypeResult @@ -1252,13 +1472,10 @@ Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, TemplateName Template = TemplateD.getAsVal<TemplateName>(); // Translate the parser's template argument list in our AST format. - llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); translateTemplateArguments(TemplateArgsIn, TemplateArgs); - QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc, - TemplateArgs.data(), - TemplateArgs.size(), - RAngleLoc); + QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs); TemplateArgsIn.release(); if (Result.isNull()) @@ -1310,64 +1527,72 @@ Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult, return ElabType.getAsOpaquePtr(); } -Sema::OwningExprResult Sema::BuildTemplateIdExpr(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TemplateName Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc) { +Sema::OwningExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL, + const TemplateArgumentListInfo &TemplateArgs) { // FIXME: Can we do any checking at this point? I guess we could check the // template arguments that we have against the template name, if the template // name refers to a single template. That's not a terribly common case, // though. - - // Cope with an implicit member access in a C++ non-static member function. - NamedDecl *D = Template.getAsTemplateDecl(); - if (!D) - D = Template.getAsOverloadedFunctionDecl(); - - CXXScopeSpec SS; - SS.setRange(QualifierRange); - SS.setScopeRep(Qualifier); - QualType ThisType, MemberType; - if (D && isImplicitMemberReference(&SS, D, TemplateNameLoc, - ThisType, MemberType)) { - Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType); - return Owned(MemberExpr::Create(Context, This, true, - Qualifier, QualifierRange, - D, TemplateNameLoc, true, - LAngleLoc, TemplateArgs, - NumTemplateArgs, RAngleLoc, - Context.OverloadTy)); + + // These should be filtered out by our callers. + assert(!R.empty() && "empty lookup results when building templateid"); + assert(!R.isAmbiguous() && "ambiguous lookup when building templateid"); + + NestedNameSpecifier *Qualifier = 0; + SourceRange QualifierRange; + if (SS.isSet()) { + Qualifier = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); + QualifierRange = SS.getRange(); } - return Owned(TemplateIdRefExpr::Create(Context, Context.OverloadTy, - Qualifier, QualifierRange, - Template, TemplateNameLoc, LAngleLoc, - TemplateArgs, - NumTemplateArgs, RAngleLoc)); + bool Dependent + = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), + &TemplateArgs); + UnresolvedLookupExpr *ULE + = UnresolvedLookupExpr::Create(Context, Dependent, + Qualifier, QualifierRange, + R.getLookupName(), R.getNameLoc(), + RequiresADL, TemplateArgs); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + ULE->addDecl(*I); + + return Owned(ULE); } -Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS, - TemplateTy TemplateD, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation RAngleLoc) { - TemplateName Template = TemplateD.getAsVal<TemplateName>(); +// We actually only call this from template instantiation. +Sema::OwningExprResult +Sema::BuildQualifiedTemplateIdExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo &TemplateArgs) { + DeclContext *DC; + if (!(DC = computeDeclContext(SS, false)) || + DC->isDependentContext() || + RequireCompleteDeclContext(SS)) + return BuildDependentDeclRefExpr(SS, Name, NameLoc, &TemplateArgs); + + LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); + LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false); + + if (R.isAmbiguous()) + return ExprError(); + + if (R.empty()) { + Diag(NameLoc, diag::err_template_kw_refers_to_non_template) + << Name << SS.getRange(); + return ExprError(); + } - // Translate the parser's template argument list in our AST format. - llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; - translateTemplateArguments(TemplateArgsIn, TemplateArgs); - TemplateArgsIn.release(); + if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) { + Diag(NameLoc, diag::err_template_kw_refers_to_class_template) + << (NestedNameSpecifier*) SS.getScopeRep() << Name << SS.getRange(); + Diag(Temp->getLocation(), diag::note_referenced_class_template); + return ExprError(); + } - return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(), - SS.getRange(), - Template, TemplateNameLoc, LAngleLoc, - TemplateArgs.data(), TemplateArgs.size(), - RAngleLoc); + return BuildTemplateIdExpr(SS, R, /* ADL */ false, TemplateArgs); } /// \brief Form a dependent template name. @@ -1381,10 +1606,11 @@ Sema::TemplateTy Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, const CXXScopeSpec &SS, UnqualifiedId &Name, - TypeTy *ObjectType) { + TypeTy *ObjectType, + bool EnteringContext) { if ((ObjectType && computeDeclContext(QualType::getFromOpaquePtr(ObjectType))) || - (SS.isSet() && computeDeclContext(SS, false))) { + (SS.isSet() && computeDeclContext(SS, EnteringContext))) { // C++0x [temp.names]p5: // If a name prefixed by the keyword template is not the name of // a template, the program is ill-formed. [Note: the keyword @@ -1403,7 +1629,7 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, // rules, even in C++03 mode, retroactively applying the DR. TemplateTy Template; TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType, - false, Template); + EnteringContext, Template); if (TNK == TNK_Non_template) { Diag(Name.getSourceRange().getBegin(), diag::err_template_kw_refers_to_non_template) @@ -1426,7 +1652,10 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, case UnqualifiedId::IK_OperatorFunctionId: return TemplateTy::make(Context.getDependentTemplateName(Qualifier, Name.OperatorFunctionId.Operator)); - + + case UnqualifiedId::IK_LiteralOperatorId: + assert(false && "We don't support these; Parse shouldn't have allowed propagation"); + default: break; } @@ -1609,6 +1838,65 @@ SubstDefaultTemplateArgument(Sema &SemaRef, AllTemplateArgs); } +/// \brief If the given template parameter has a default template +/// argument, substitute into that default template argument and +/// return the corresponding template argument. +TemplateArgumentLoc +Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + Decl *Param, + TemplateArgumentListBuilder &Converted) { + if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) { + if (!TypeParm->hasDefaultArgument()) + return TemplateArgumentLoc(); + + DeclaratorInfo *DI = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + TypeParm, + Converted); + if (DI) + return TemplateArgumentLoc(TemplateArgument(DI->getType()), DI); + + return TemplateArgumentLoc(); + } + + if (NonTypeTemplateParmDecl *NonTypeParm + = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + if (!NonTypeParm->hasDefaultArgument()) + return TemplateArgumentLoc(); + + OwningExprResult Arg = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + NonTypeParm, + Converted); + if (Arg.isInvalid()) + return TemplateArgumentLoc(); + + Expr *ArgE = Arg.takeAs<Expr>(); + return TemplateArgumentLoc(TemplateArgument(ArgE), ArgE); + } + + TemplateTemplateParmDecl *TempTempParm + = cast<TemplateTemplateParmDecl>(Param); + if (!TempTempParm->hasDefaultArgument()) + return TemplateArgumentLoc(); + + TemplateName TName = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + TempTempParm, + Converted); + if (TName.isNull()) + return TemplateArgumentLoc(); + + return TemplateArgumentLoc(TemplateArgument(TName), + TempTempParm->getDefaultArgument().getTemplateQualifierRange(), + TempTempParm->getDefaultArgument().getTemplateNameLoc()); +} + /// \brief Check that the given template argument corresponds to the given /// template parameter. bool Sema::CheckTemplateArgument(NamedDecl *Param, @@ -1679,12 +1967,11 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, // parsed as a template template argument. However, since we now // know that we need a non-type template argument, convert this // template name into an expression. - Expr *E = new (Context) UnresolvedDeclRefExpr(DTN->getIdentifier(), - Context.DependentTy, - Arg.getTemplateNameLoc(), + Expr *E = DependentScopeDeclRefExpr::Create(Context, + DTN->getQualifier(), Arg.getTemplateQualifierRange(), - DTN->getQualifier(), - /*isAddressOfOperand=*/false); + DTN->getIdentifier(), + Arg.getTemplateNameLoc()); TemplateArgument Result; if (CheckTemplateArgument(NTTP, NTTPType, E, Result)) @@ -1798,17 +2085,16 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, /// for specializing the given template. bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc, + const TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, TemplateArgumentListBuilder &Converted) { TemplateParameterList *Params = Template->getTemplateParameters(); unsigned NumParams = Params->size(); - unsigned NumArgs = NumTemplateArgs; + unsigned NumArgs = TemplateArgs.size(); bool Invalid = false; + SourceLocation RAngleLoc = TemplateArgs.getRAngleLoc(); + bool HasParameterPack = NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack(); @@ -2048,7 +2334,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, // Functions must have external linkage. if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) { - if (Func->getStorageClass() == FunctionDecl::Static) { + if (Func->getLinkage() != NamedDecl::ExternalLinkage) { Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_function_not_extern) << Func << Arg->getSourceRange(); @@ -2063,7 +2349,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, } if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { - if (!Var->hasGlobalStorage()) { + if (Var->getLinkage() != NamedDecl::ExternalLinkage) { Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_object_not_extern) << Var << Arg->getSourceRange(); @@ -3046,16 +3332,17 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, } // Translate the parser's template argument list in our AST format. - llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; + TemplateArgumentListInfo TemplateArgs; + TemplateArgs.setLAngleLoc(LAngleLoc); + TemplateArgs.setRAngleLoc(RAngleLoc); translateTemplateArguments(TemplateArgsIn, TemplateArgs); // Check that the template argument list is well-formed for this // template. TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(), TemplateArgs.size()); - if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, - TemplateArgs.data(), TemplateArgs.size(), - RAngleLoc, false, Converted)) + if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, + TemplateArgs, false, Converted)) return true; assert((Converted.structuredSize() == @@ -3154,8 +3441,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TemplateParams, ClassTemplate, Converted, - TemplateArgs.data(), - TemplateArgs.size(), + TemplateArgs, PrevPartial); if (PrevPartial) { @@ -3267,10 +3553,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // name based on the "canonical" representation used to store the // template arguments in the specialization. QualType WrittenTy - = Context.getTemplateSpecializationType(Name, - TemplateArgs.data(), - TemplateArgs.size(), - CanonType); + = Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType); if (TUK != TUK_Friend) Specialization->setTypeAsWritten(WrittenTy); TemplateArgsIn.release(); @@ -3533,11 +3816,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, /// \param PrevDecl the set of declarations that bool Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, - bool HasExplicitTemplateArgs, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, - SourceLocation RAngleLoc, + const TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous) { // The set of function template specializations that could match this // explicit function template specialization. @@ -3564,9 +3843,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, TemplateDeductionInfo Info(Context); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK - = DeduceTemplateArguments(FunTmpl, HasExplicitTemplateArgs, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, + = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, FD->getType(), Specialization, Info)) { @@ -3589,7 +3866,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, PartialDiagnostic(diag::err_function_template_spec_no_match) << FD->getDeclName(), PartialDiagnostic(diag::err_function_template_spec_ambiguous) - << FD->getDeclName() << HasExplicitTemplateArgs, + << FD->getDeclName() << (ExplicitTemplateArgs != 0), PartialDiagnostic(diag::note_function_template_spec_matched)); if (!Specialization) return true; @@ -3901,16 +4178,15 @@ Sema::ActOnExplicitInstantiation(Scope *S, : TSK_ExplicitInstantiationDeclaration; // Translate the parser's template argument list in our AST format. - llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); translateTemplateArguments(TemplateArgsIn, TemplateArgs); // Check that the template argument list is well-formed for this // template. TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(), TemplateArgs.size()); - if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, - TemplateArgs.data(), TemplateArgs.size(), - RAngleLoc, false, Converted)) + if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, + TemplateArgs, false, Converted)) return true; assert((Converted.structuredSize() == @@ -3938,6 +4214,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, ClassTemplateSpecializationDecl *Specialization = 0; + bool ReusedDecl = false; if (PrevDecl) { bool SuppressNew = false; if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK, @@ -3959,6 +4236,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization = PrevDecl; Specialization->setLocation(TemplateNameLoc); PrevDecl = 0; + ReusedDecl = true; } } @@ -3991,18 +4269,18 @@ Sema::ActOnExplicitInstantiation(Scope *S, // on the "canonical" representation used to store the template // arguments in the specialization. QualType WrittenTy - = Context.getTemplateSpecializationType(Name, - TemplateArgs.data(), - TemplateArgs.size(), + = Context.getTemplateSpecializationType(Name, TemplateArgs, Context.getTypeDeclType(Specialization)); Specialization->setTypeAsWritten(WrittenTy); TemplateArgsIn.release(); - // Add the explicit instantiation into its lexical context. However, - // since explicit instantiations are never found by name lookup, we - // just put it into the declaration context directly. - Specialization->setLexicalDeclContext(CurContext); - CurContext->addDecl(Specialization); + if (!ReusedDecl) { + // Add the explicit instantiation into its lexical context. However, + // since explicit instantiations are never found by name lookup, we + // just put it into the declaration context directly. + Specialization->setLexicalDeclContext(CurContext); + CurContext->addDecl(Specialization); + } // C++ [temp.explicit]p3: // A definition of a class template or class member template @@ -4277,14 +4555,15 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // If the declarator is a template-id, translate the parser's template // argument list into our AST format. bool HasExplicitTemplateArgs = false; - llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; + TemplateArgumentListInfo TemplateArgs; if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { TemplateIdAnnotation *TemplateId = D.getName().TemplateId; + TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc); + TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc); ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), TemplateId->NumArgs); - translateTemplateArguments(TemplateArgsPtr, - TemplateArgs); + translateTemplateArguments(TemplateArgsPtr, TemplateArgs); HasExplicitTemplateArgs = true; TemplateArgsPtr.release(); } @@ -4315,8 +4594,8 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, TemplateDeductionInfo Info(Context); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK - = DeduceTemplateArguments(FunTmpl, HasExplicitTemplateArgs, - TemplateArgs.data(), TemplateArgs.size(), + = DeduceTemplateArguments(FunTmpl, + (HasExplicitTemplateArgs ? &TemplateArgs : 0), R, Specialization, Info)) { // FIXME: Keep track of almost-matches? (void)TDK; @@ -4365,12 +4644,12 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (SuppressNew) return DeclPtrTy(); } + + Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); if (TSK == TSK_ExplicitInstantiationDefinition) InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization, false, /*DefinitionRequired=*/true); - - Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); // C++0x [temp.explicit]p2: // If the explicit instantiation is for a member function, a member class @@ -4537,7 +4816,7 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, namespace { // See Sema::RebuildTypeInCurrentInstantiation - class VISIBILITY_HIDDEN CurrentInstantiationRebuilder + class CurrentInstantiationRebuilder : public TreeTransform<CurrentInstantiationRebuilder> { SourceLocation Loc; DeclarationName Entity; diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 10594c7..613ffde 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -17,7 +17,6 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/Parse/DeclSpec.h" -#include "llvm/Support/Compiler.h" #include <algorithm> namespace clang { @@ -1050,35 +1049,34 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, const TemplateArgumentLoc *PartialTemplateArgs = Partial->getTemplateArgsAsWritten(); unsigned N = Partial->getNumTemplateArgsAsWritten(); - llvm::SmallVector<TemplateArgumentLoc, 16> InstArgs(N); + + // Note that we don't provide the langle and rangle locations. + TemplateArgumentListInfo InstArgs; + for (unsigned I = 0; I != N; ++I) { Decl *Param = const_cast<NamedDecl *>( ClassTemplate->getTemplateParameters()->getParam(I)); - if (Subst(PartialTemplateArgs[I], InstArgs[I], + TemplateArgumentLoc InstArg; + if (Subst(PartialTemplateArgs[I], InstArg, MultiLevelTemplateArgumentList(*DeducedArgumentList))) { Info.Param = makeTemplateParameter(Param); Info.FirstArg = PartialTemplateArgs[I].getArgument(); return TDK_SubstitutionFailure; } + InstArgs.addArgument(InstArg); } TemplateArgumentListBuilder ConvertedInstArgs( ClassTemplate->getTemplateParameters(), N); if (CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(), - /*LAngle*/ SourceLocation(), - InstArgs.data(), N, - /*RAngle*/ SourceLocation(), - false, ConvertedInstArgs)) { + InstArgs, false, ConvertedInstArgs)) { // FIXME: fail with more useful information? return TDK_SubstitutionFailure; } for (unsigned I = 0, E = ConvertedInstArgs.flatSize(); I != E; ++I) { - // We don't really care if we overwrite the internal structures of - // the arg list builder, because we're going to throw it all away. - TemplateArgument &InstArg - = const_cast<TemplateArgument&>(ConvertedInstArgs.getFlatArguments()[I]); + TemplateArgument InstArg = ConvertedInstArgs.getFlatArguments()[I]; Decl *Param = const_cast<NamedDecl *>( ClassTemplate->getTemplateParameters()->getParam(I)); @@ -1130,9 +1128,6 @@ static bool isSimpleTemplateIdType(QualType T) { /// \param ExplicitTemplateArguments the explicitly-specified template /// arguments. /// -/// \param NumExplicitTemplateArguments the number of explicitly-specified -/// template arguments in @p ExplicitTemplateArguments. This value may be zero. -/// /// \param Deduced the deduced template arguments, which will be populated /// with the converted and checked explicit template arguments. /// @@ -1151,8 +1146,7 @@ static bool isSimpleTemplateIdType(QualType T) { Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo &ExplicitTemplateArgs, llvm::SmallVectorImpl<TemplateArgument> &Deduced, llvm::SmallVectorImpl<QualType> &ParamTypes, QualType *FunctionType, @@ -1161,7 +1155,7 @@ Sema::SubstituteExplicitTemplateArguments( TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); - if (NumExplicitTemplateArgs == 0) { + if (ExplicitTemplateArgs.size() == 0) { // No arguments to substitute; just copy over the parameter types and // fill in the function type. for (FunctionDecl::param_iterator P = Function->param_begin(), @@ -1185,7 +1179,7 @@ Sema::SubstituteExplicitTemplateArguments( // template argument list shall not specify more template-arguments than // there are corresponding template-parameters. TemplateArgumentListBuilder Builder(TemplateParams, - NumExplicitTemplateArgs); + ExplicitTemplateArgs.size()); // Enter a new template instantiation context where we check the // explicitly-specified template arguments against this function template, @@ -1197,10 +1191,8 @@ Sema::SubstituteExplicitTemplateArguments( return TDK_InstantiationDepth; if (CheckTemplateArgumentList(FunctionTemplate, - SourceLocation(), SourceLocation(), - ExplicitTemplateArgs, - NumExplicitTemplateArgs, SourceLocation(), + ExplicitTemplateArgs, true, Builder) || Trap.hasErrorOccurred()) return TDK_InvalidExplicitArguments; @@ -1279,18 +1271,56 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); + // Template argument deduction for function templates in a SFINAE context. + // Trap any errors that might occur. + SFINAETrap Trap(*this); + + // Enter a new template instantiation context while we instantiate the + // actual function declaration. + InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), + FunctionTemplate, Deduced.data(), Deduced.size(), + ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution); + if (Inst) + return TDK_InstantiationDepth; + // C++ [temp.deduct.type]p2: // [...] or if any template argument remains neither deduced nor // explicitly specified, template argument deduction fails. TemplateArgumentListBuilder Builder(TemplateParams, Deduced.size()); for (unsigned I = 0, N = Deduced.size(); I != N; ++I) { - if (Deduced[I].isNull()) { + if (!Deduced[I].isNull()) { + Builder.Append(Deduced[I]); + continue; + } + + // Substitute into the default template argument, if available. + NamedDecl *Param = FunctionTemplate->getTemplateParameters()->getParam(I); + TemplateArgumentLoc DefArg + = SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate, + FunctionTemplate->getLocation(), + FunctionTemplate->getSourceRange().getEnd(), + Param, + Builder); + + // If there was no default argument, deduction is incomplete. + if (DefArg.getArgument().isNull()) { Info.Param = makeTemplateParameter( - const_cast<NamedDecl *>(TemplateParams->getParam(I))); + const_cast<NamedDecl *>(TemplateParams->getParam(I))); return TDK_Incomplete; } + + // Check whether we can actually use the default argument. + if (CheckTemplateArgument(Param, DefArg, + FunctionTemplate, + FunctionTemplate->getLocation(), + FunctionTemplate->getSourceRange().getEnd(), + Builder)) { + Info.Param = makeTemplateParameter( + const_cast<NamedDecl *>(TemplateParams->getParam(I))); + return TDK_SubstitutionFailure; + } - Builder.Append(Deduced[I]); + // If we get here, we successfully used the default template argument. } // Form the template argument list from the deduced template arguments. @@ -1298,18 +1328,6 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true); Info.reset(DeducedArgumentList); - // Template argument deduction for function templates in a SFINAE context. - // Trap any errors that might occur. - SFINAETrap Trap(*this); - - // Enter a new template instantiation context while we instantiate the - // actual function declaration. - InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), - FunctionTemplate, Deduced.data(), Deduced.size(), - ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution); - if (Inst) - return TDK_InstantiationDepth; - // Substitute the deduced template arguments into the function template // declaration to produce the function template specialization. Specialization = cast_or_null<FunctionDecl>( @@ -1368,9 +1386,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, /// \returns the result of template argument deduction. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { @@ -1398,11 +1414,10 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, = FunctionTemplate->getTemplateParameters(); llvm::SmallVector<TemplateArgument, 4> Deduced; llvm::SmallVector<QualType, 4> ParamTypes; - if (NumExplicitTemplateArgs) { + if (ExplicitTemplateArgs) { TemplateDeductionResult Result = SubstituteExplicitTemplateArguments(FunctionTemplate, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, + *ExplicitTemplateArgs, Deduced, ParamTypes, 0, @@ -1538,9 +1553,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, /// \returns the result of template argument deduction. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - bool HasExplicitTemplateArgs, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, + const TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType, FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { @@ -1552,11 +1565,10 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // Substitute any explicit template arguments. llvm::SmallVector<TemplateArgument, 4> Deduced; llvm::SmallVector<QualType, 4> ParamTypes; - if (HasExplicitTemplateArgs) { + if (ExplicitTemplateArgs) { if (TemplateDeductionResult Result = SubstituteExplicitTemplateArguments(FunctionTemplate, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, + *ExplicitTemplateArgs, Deduced, ParamTypes, &FunctionType, Info)) return Result; diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 58fe59e..623cde8 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -12,13 +12,13 @@ #include "Sema.h" #include "TreeTransform.h" +#include "Lookup.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/AST/DeclTemplate.h" #include "clang/Parse/DeclSpec.h" #include "clang/Basic/LangOptions.h" -#include "llvm/Support/Compiler.h" using namespace clang; @@ -491,7 +491,7 @@ bool Sema::isSFINAEContext() const { // Template Instantiation for Types //===----------------------------------------------------------------------===/ namespace { - class VISIBILITY_HIDDEN TemplateInstantiator + class TemplateInstantiator : public TreeTransform<TemplateInstantiator> { const MultiLevelTemplateArgumentList &TemplateArgs; SourceLocation Loc; @@ -743,7 +743,6 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, = SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), E->getLocation(), - /*FIXME:*/false, /*FIXME:*/false, &SS); if (RefExpr.isInvalid()) return SemaRef.ExprError(); @@ -755,8 +754,7 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, } return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), - E->getLocation(), - /*FIXME:*/false, /*FIXME:*/false); + E->getLocation()); } assert(Arg.getKind() == TemplateArgument::Integral); @@ -788,46 +786,7 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, if (!InstD) return SemaRef.ExprError(); - // Flatten using declarations into their shadow declarations. - if (isa<UsingDecl>(InstD)) { - UsingDecl *UD = cast<UsingDecl>(InstD); - - bool HasNonFunction = false; - - llvm::SmallVector<NamedDecl*, 8> Decls; - for (UsingDecl::shadow_iterator I = UD->shadow_begin(), - E = UD->shadow_end(); I != E; ++I) { - NamedDecl *TD = (*I)->getTargetDecl(); - if (!TD->isFunctionOrFunctionTemplate()) - HasNonFunction = true; - - Decls.push_back(TD); - } - - if (Decls.empty()) - return SemaRef.ExprError(); - - if (Decls.size() == 1) - InstD = Decls[0]; - else if (!HasNonFunction) { - OverloadedFunctionDecl *OFD - = OverloadedFunctionDecl::Create(SemaRef.Context, - UD->getDeclContext(), - UD->getDeclName()); - for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Decls.begin(), - E = Decls.end(); I != E; ++I) - if (isa<FunctionDecl>(*I)) - OFD->addOverload(cast<FunctionDecl>(*I)); - else - OFD->addOverload(cast<FunctionTemplateDecl>(*I)); - - InstD = OFD; - } else { - // FIXME - assert(false && "using declaration resolved to mixed set"); - return SemaRef.ExprError(); - } - } + assert(!isa<UsingDecl>(InstD) && "decl ref instantiated to UsingDecl"); CXXScopeSpec SS; NestedNameSpecifier *Qualifier = 0; @@ -841,10 +800,7 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, SS.setRange(E->getQualifierRange()); } - return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD, - /*FIXME:*/false, - &SS, - isAddressOfOperand); + return SemaRef.BuildDeclarationNameExpr(SS, E->getLocation(), InstD); } Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr( diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 3f40ffc..a125857 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -18,12 +18,11 @@ #include "clang/AST/Expr.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/Support/Compiler.h" using namespace clang; namespace { - class VISIBILITY_HIDDEN TemplateDeclInstantiator + class TemplateDeclInstantiator : public DeclVisitor<TemplateDeclInstantiator, Decl *> { Sema &SemaRef; DeclContext *Owner; @@ -205,6 +204,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // we don't want to redo all the checking, especially since the // initializer might have been wrapped by a CXXConstructExpr since we did // it the first time. + Var->setType(D->getType()); Var->setInit(SemaRef.Context, Init.takeAs<Expr>()); } else if (ParenListExpr *PLE = dyn_cast<ParenListExpr>((Expr *)Init.get())) { @@ -1153,11 +1153,12 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( = PartialSpec->getTemplateArgsAsWritten(); unsigned N = PartialSpec->getNumTemplateArgsAsWritten(); - llvm::SmallVector<TemplateArgumentLoc, 4> InstTemplateArgs(N); + TemplateArgumentListInfo InstTemplateArgs; // no angle locations for (unsigned I = 0; I != N; ++I) { - if (SemaRef.Subst(PartialSpecTemplateArgs[I], InstTemplateArgs[I], - TemplateArgs)) + TemplateArgumentLoc Loc; + if (SemaRef.Subst(PartialSpecTemplateArgs[I], Loc, TemplateArgs)) return true; + InstTemplateArgs.addArgument(Loc); } @@ -1167,10 +1168,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( InstTemplateArgs.size()); if (SemaRef.CheckTemplateArgumentList(ClassTemplate, PartialSpec->getLocation(), - /*FIXME:*/PartialSpec->getLocation(), - InstTemplateArgs.data(), - InstTemplateArgs.size(), - /*FIXME:*/PartialSpec->getLocation(), + InstTemplateArgs, false, Converted)) return true; @@ -1203,8 +1201,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // template arguments in the specialization. QualType WrittenTy = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate), - InstTemplateArgs.data(), - InstTemplateArgs.size(), + InstTemplateArgs, CanonType); if (PrevDecl) { @@ -1238,8 +1235,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( InstParams, ClassTemplate, Converted, - InstTemplateArgs.data(), - InstTemplateArgs.size(), + InstTemplateArgs, 0); InstPartialSpec->setInstantiatedFromMember(PartialSpec); InstPartialSpec->setTypeAsWritten(WrittenTy); @@ -1887,22 +1883,6 @@ DeclContext *Sema::FindInstantiatedContext(DeclContext* DC, /// this mapping from within the instantiation of X<int>. NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs) { - if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) { - // Transform all of the elements of the overloaded function set. - OverloadedFunctionDecl *Result - = OverloadedFunctionDecl::Create(Context, CurContext, Ovl->getDeclName()); - - for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(), - FEnd = Ovl->function_end(); - F != FEnd; ++F) { - Result->addOverload( - AnyFunctionDecl::getFromNamedDecl(FindInstantiatedDecl(*F, - TemplateArgs))); - } - - return Result; - } - DeclContext *ParentDC = D->getDeclContext(); if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) || isa<TemplateTypeParmDecl>(D) || diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 00dc809..afce5e3 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -879,6 +879,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, switch (D.getName().getKind()) { case UnqualifiedId::IK_Identifier: case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedId::IK_LiteralOperatorId: case UnqualifiedId::IK_TemplateId: T = ConvertDeclSpecToType(D, *this); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index ca680c2..28b2174 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_SEMA_TREETRANSFORM_H #include "Sema.h" +#include "Lookup.h" #include "clang/Sema/SemaDiagnostic.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" @@ -94,7 +95,8 @@ public: typedef Sema::ExprArg ExprArg; typedef Sema::MultiExprArg MultiExprArg; typedef Sema::MultiStmtArg MultiStmtArg; - + typedef Sema::DeclPtrTy DeclPtrTy; + /// \brief Initializes a new tree transformer. TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { } @@ -503,10 +505,7 @@ public: /// different behavior. QualType RebuildTemplateSpecializationType(TemplateName Template, SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *Args, - unsigned NumArgs, - SourceLocation RAngleLoc); + const TemplateArgumentListInfo &Args); /// \brief Build a new qualified name type. /// @@ -584,16 +583,6 @@ public: bool TemplateKW, TemplateDecl *Template); - /// \brief Build a new template name given a nested name specifier, a flag - /// indicating whether the "template" keyword was provided, and a set of - /// overloaded function templates. - /// - /// By default, builds the new template name directly. Subclasses may override - /// this routine to provide different behavior. - TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier, - bool TemplateKW, - OverloadedFunctionDecl *Ovl); - /// \brief Build a new template name given a nested name specifier and the /// name that is referred to as a template. /// @@ -677,17 +666,19 @@ public: /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. OwningStmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::FullExprArg Cond, - StmtArg Then, SourceLocation ElseLoc, - StmtArg Else) { - return getSema().ActOnIfStmt(IfLoc, Cond, move(Then), ElseLoc, move(Else)); + VarDecl *CondVar, StmtArg Then, + SourceLocation ElseLoc, StmtArg Else) { + return getSema().ActOnIfStmt(IfLoc, Cond, DeclPtrTy::make(CondVar), + move(Then), ElseLoc, move(Else)); } /// \brief Start building a new switch statement. /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - OwningStmtResult RebuildSwitchStmtStart(ExprArg Cond) { - return getSema().ActOnStartOfSwitchStmt(move(Cond)); + OwningStmtResult RebuildSwitchStmtStart(Sema::FullExprArg Cond, + VarDecl *CondVar) { + return getSema().ActOnStartOfSwitchStmt(Cond, DeclPtrTy::make(CondVar)); } /// \brief Attach the body to the switch statement. @@ -706,8 +697,10 @@ public: /// Subclasses may override this routine to provide different behavior. OwningStmtResult RebuildWhileStmt(SourceLocation WhileLoc, Sema::FullExprArg Cond, + VarDecl *CondVar, StmtArg Body) { - return getSema().ActOnWhileStmt(WhileLoc, Cond, move(Body)); + return getSema().ActOnWhileStmt(WhileLoc, Cond, DeclPtrTy::make(CondVar), + move(Body)); } /// \brief Build a new do-while statement. @@ -729,10 +722,12 @@ public: /// Subclasses may override this routine to provide different behavior. OwningStmtResult RebuildForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - StmtArg Init, ExprArg Cond, ExprArg Inc, + StmtArg Init, Sema::FullExprArg Cond, + VarDecl *CondVar, Sema::FullExprArg Inc, SourceLocation RParenLoc, StmtArg Body) { - return getSema().ActOnForStmt(ForLoc, LParenLoc, move(Init), move(Cond), - move(Inc), RParenLoc, move(Body)); + return getSema().ActOnForStmt(ForLoc, LParenLoc, move(Init), Cond, + DeclPtrTy::make(CondVar), + Inc, RParenLoc, move(Body)); } /// \brief Build a new goto statement. @@ -818,6 +813,17 @@ public: /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. + OwningExprResult RebuildDeclarationNameExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL) { + return getSema().BuildDeclarationNameExpr(SS, R, RequiresADL); + } + + + /// \brief Build a new expression that references a declaration. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. OwningExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, NamedDecl *ND, SourceLocation Loc, @@ -861,13 +867,10 @@ public: = SemaRef.Context.DeclarationNames.getCXXDestructorName( SemaRef.Context.getCanonicalType(DestroyedType)); - return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), - OperatorLoc, - isArrow? tok::arrow : tok::period, - DestroyedTypeLoc, - Name, - Sema::DeclPtrTy::make((Decl *)0), - &SS); + return getSema().BuildMemberReferenceExpr(move(Base), OperatorLoc, isArrow, + SS, /*FIXME: FirstQualifier*/ 0, + Name, DestroyedTypeLoc, + /*TemplateArgs*/ 0); } /// \brief Build a new unary operator expression. @@ -942,11 +945,7 @@ public: SourceRange QualifierRange, SourceLocation MemberLoc, NamedDecl *Member, - bool HasExplicitTemplateArgs, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, - SourceLocation RAngleLoc, + const TemplateArgumentListInfo *ExplicitTemplateArgs, NamedDecl *FirstQualifierInScope) { if (!Member->getDeclName()) { // We have a reference to an unnamed field. @@ -965,18 +964,10 @@ public: SS.setScopeRep(Qualifier); } - return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc, - isArrow? tok::arrow : tok::period, - MemberLoc, - Member->getDeclName(), - HasExplicitTemplateArgs, - LAngleLoc, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, - RAngleLoc, - /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0), - &SS, - FirstQualifierInScope); + return getSema().BuildMemberReferenceExpr(move(Base), OpLoc, isArrow, + SS, FirstQualifierInScope, + Member->getDeclName(), MemberLoc, + ExplicitTemplateArgs); } /// \brief Build a new binary operator expression. @@ -1051,10 +1042,13 @@ public: SourceLocation OpLoc, SourceLocation AccessorLoc, IdentifierInfo &Accessor) { - return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc, - tok::period, AccessorLoc, + CXXScopeSpec SS; + return getSema().BuildMemberReferenceExpr(move(Base), + OpLoc, /*IsArrow*/ false, + SS, /*FirstQualifierInScope*/ 0, DeclarationName(&Accessor), - /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0)); + AccessorLoc, + /* TemplateArgs */ 0); } /// \brief Build a new initializer list expression. @@ -1122,7 +1116,8 @@ public: OwningExprResult RebuildParenListExpr(SourceLocation LParenLoc, MultiExprArg SubExprs, SourceLocation RParenLoc) { - return getSema().ActOnParenListExpr(LParenLoc, RParenLoc, move(SubExprs)); + return getSema().ActOnParenOrParenListExpr(LParenLoc, RParenLoc, + move(SubExprs)); } /// \brief Build a new address-of-label expression. @@ -1383,18 +1378,6 @@ public: 0, RParenLoc); } - /// \brief Build a new C++ conditional declaration expression. - /// - /// By default, performs semantic analysis to build the new expression. - /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildCXXConditionDeclExpr(SourceLocation StartLoc, - SourceLocation EqLoc, - VarDecl *Var) { - return SemaRef.Owned(new (SemaRef.Context) CXXConditionDeclExpr(StartLoc, - EqLoc, - Var)); - } - /// \brief Build a new C++ "new" expression. /// /// By default, performs semantic analysis to build the new expression. @@ -1456,39 +1439,31 @@ public: /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildUnresolvedDeclRefExpr(NestedNameSpecifier *NNS, + OwningExprResult RebuildDependentScopeDeclRefExpr(NestedNameSpecifier *NNS, SourceRange QualifierRange, DeclarationName Name, SourceLocation Location, - bool IsAddressOfOperand) { + const TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; SS.setRange(QualifierRange); SS.setScopeRep(NNS); - return getSema().ActOnDeclarationNameExpr(/*Scope=*/0, - Location, - Name, - /*Trailing lparen=*/false, - &SS, - IsAddressOfOperand); + + if (TemplateArgs) + return getSema().BuildQualifiedTemplateIdExpr(SS, Name, Location, + *TemplateArgs); + + return getSema().BuildQualifiedDeclarationNameExpr(SS, Name, Location); } /// \brief Build a new template-id expression. /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildTemplateIdExpr(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TemplateName Template, - SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc) { - return getSema().BuildTemplateIdExpr(Qualifier, QualifierRange, - Template, TemplateLoc, - LAngleLoc, - TemplateArgs, NumTemplateArgs, - RAngleLoc); + OwningExprResult RebuildTemplateIdExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL, + const TemplateArgumentListInfo &TemplateArgs) { + return getSema().BuildTemplateIdExpr(SS, R, RequiresADL, TemplateArgs); } /// \brief Build a new object-construction expression. @@ -1546,76 +1521,43 @@ public: /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildCXXUnresolvedMemberExpr(ExprArg BaseE, + OwningExprResult RebuildCXXDependentScopeMemberExpr(ExprArg BaseE, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + NamedDecl *FirstQualifierInScope, DeclarationName Name, SourceLocation MemberLoc, - NamedDecl *FirstQualifierInScope) { - OwningExprResult Base = move(BaseE); - tok::TokenKind OpKind = IsArrow? tok::arrow : tok::period; - + const TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; SS.setRange(QualifierRange); SS.setScopeRep(Qualifier); - return SemaRef.BuildMemberReferenceExpr(/*Scope=*/0, - move(Base), OperatorLoc, OpKind, - MemberLoc, - Name, - /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0), - &SS, - FirstQualifierInScope); + return SemaRef.BuildMemberReferenceExpr(move(BaseE), OperatorLoc, IsArrow, + SS, FirstQualifierInScope, + Name, MemberLoc, TemplateArgs); } - /// \brief Build a new member reference expression with explicit template - /// arguments. + /// \brief Build a new member reference expression. /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildCXXUnresolvedMemberExpr(ExprArg BaseE, - bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TemplateName Template, - SourceLocation TemplateNameLoc, - NamedDecl *FirstQualifierInScope, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc) { + OwningExprResult RebuildUnresolvedMemberExpr(ExprArg BaseE, + SourceLocation OperatorLoc, + bool IsArrow, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs) { OwningExprResult Base = move(BaseE); - tok::TokenKind OpKind = IsArrow? tok::arrow : tok::period; CXXScopeSpec SS; SS.setRange(QualifierRange); SS.setScopeRep(Qualifier); - // FIXME: We're going to end up looking up the template based on its name, - // twice! Also, duplicates part of Sema::BuildMemberAccessExpr. - DeclarationName Name; - if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl()) - Name = ActualTemplate->getDeclName(); - else if (OverloadedFunctionDecl *Ovl - = Template.getAsOverloadedFunctionDecl()) - Name = Ovl->getDeclName(); - else { - DependentTemplateName *DTN = Template.getAsDependentTemplateName(); - if (DTN->isIdentifier()) - Name = DTN->getIdentifier(); - else - Name = SemaRef.Context.DeclarationNames.getCXXOperatorName( - DTN->getOperator()); - } - return SemaRef.BuildMemberReferenceExpr(/*Scope=*/0, move(Base), - OperatorLoc, OpKind, - TemplateNameLoc, Name, true, - LAngleLoc, TemplateArgs, - NumTemplateArgs, RAngleLoc, - Sema::DeclPtrTy(), &SS); + return SemaRef.BuildMemberReferenceExpr(move(Base), OperatorLoc, IsArrow, + SS, R, TemplateArgs); } /// \brief Build a new Objective-C @encode expression. @@ -1664,7 +1606,7 @@ public: FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first); Expr *Callee = new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(), - BuiltinLoc, false, false); + BuiltinLoc); SemaRef.UsualUnaryConversions(Callee); // Build the CallExpr @@ -1825,6 +1767,7 @@ TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name, case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: case DeclarationName::CXXOperatorName: + case DeclarationName::CXXLiteralOperatorName: case DeclarationName::CXXUsingDirective: return Name; @@ -1878,20 +1821,8 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name, TransTemplate); } - OverloadedFunctionDecl *Ovl = QTN->getOverloadedFunctionDecl(); - assert(Ovl && "Not a template name or an overload set?"); - OverloadedFunctionDecl *TransOvl - = cast_or_null<OverloadedFunctionDecl>(getDerived().TransformDecl(Ovl)); - if (!TransOvl) - return TemplateName(); - - if (!getDerived().AlwaysRebuild() && - NNS == QTN->getQualifier() && - TransOvl == Ovl) - return Name; - - return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(), - TransOvl); + // These should be getting filtered out before they make it into the AST. + assert(false && "overloaded template name survived to here"); } if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) { @@ -1927,18 +1858,9 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name, return TemplateName(TransTemplate); } - OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl(); - assert(Ovl && "Not a template name or an overload set?"); - OverloadedFunctionDecl *TransOvl - = cast_or_null<OverloadedFunctionDecl>(getDerived().TransformDecl(Ovl)); - if (!TransOvl) - return TemplateName(); - - if (!getDerived().AlwaysRebuild() && - TransOvl == Ovl) - return Name; - - return TemplateName(TransOvl); + // These should be getting filtered out before they reach the AST. + assert(false && "overloaded function decl survived to here"); + return TemplateName(); } template<typename Derived> @@ -2879,21 +2801,23 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType( if (Template.isNull()) return QualType(); - llvm::SmallVector<TemplateArgumentLoc, 4> NewTemplateArgs(T->getNumArgs()); - for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) - if (getDerived().TransformTemplateArgument(TL.getArgLoc(i), - NewTemplateArgs[i])) + TemplateArgumentListInfo NewTemplateArgs; + NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); + NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); + + for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) { + TemplateArgumentLoc Loc; + if (getDerived().TransformTemplateArgument(TL.getArgLoc(i), Loc)) return QualType(); + NewTemplateArgs.addArgument(Loc); + } // FIXME: maybe don't rebuild if all the template arguments are the same. QualType Result = getDerived().RebuildTemplateSpecializationType(Template, TL.getTemplateNameLoc(), - TL.getLAngleLoc(), - NewTemplateArgs.data(), - NewTemplateArgs.size(), - TL.getRAngleLoc()); + NewTemplateArgs); if (!Result.isNull()) { TemplateSpecializationTypeLoc NewTL @@ -3103,10 +3027,21 @@ template<typename Derived> Sema::OwningStmtResult TreeTransform<Derived>::TransformIfStmt(IfStmt *S) { // Transform the condition - OwningExprResult Cond = getDerived().TransformExpr(S->getCond()); - if (Cond.isInvalid()) - return SemaRef.StmtError(); - + OwningExprResult Cond(SemaRef); + VarDecl *ConditionVar = 0; + if (S->getConditionVariable()) { + ConditionVar + = cast_or_null<VarDecl>( + getDerived().TransformDefinition(S->getConditionVariable())); + if (!ConditionVar) + return SemaRef.StmtError(); + } else { + Cond = getDerived().TransformExpr(S->getCond()); + + if (Cond.isInvalid()) + return SemaRef.StmtError(); + } + Sema::FullExprArg FullCond(getSema().FullExpr(Cond)); // Transform the "then" branch. @@ -3121,11 +3056,13 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) { if (!getDerived().AlwaysRebuild() && FullCond->get() == S->getCond() && + ConditionVar == S->getConditionVariable() && Then.get() == S->getThen() && Else.get() == S->getElse()) return SemaRef.Owned(S->Retain()); - return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, move(Then), + return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, ConditionVar, + move(Then), S->getElseLoc(), move(Else)); } @@ -3133,12 +3070,26 @@ template<typename Derived> Sema::OwningStmtResult TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) { // Transform the condition. - OwningExprResult Cond = getDerived().TransformExpr(S->getCond()); - if (Cond.isInvalid()) - return SemaRef.StmtError(); + OwningExprResult Cond(SemaRef); + VarDecl *ConditionVar = 0; + if (S->getConditionVariable()) { + ConditionVar + = cast_or_null<VarDecl>( + getDerived().TransformDefinition(S->getConditionVariable())); + if (!ConditionVar) + return SemaRef.StmtError(); + } else { + Cond = getDerived().TransformExpr(S->getCond()); + + if (Cond.isInvalid()) + return SemaRef.StmtError(); + } + Sema::FullExprArg FullCond(getSema().FullExpr(Cond)); + // Rebuild the switch statement. - OwningStmtResult Switch = getDerived().RebuildSwitchStmtStart(move(Cond)); + OwningStmtResult Switch = getDerived().RebuildSwitchStmtStart(FullCond, + ConditionVar); if (Switch.isInvalid()) return SemaRef.StmtError(); @@ -3156,9 +3107,20 @@ template<typename Derived> Sema::OwningStmtResult TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) { // Transform the condition - OwningExprResult Cond = getDerived().TransformExpr(S->getCond()); - if (Cond.isInvalid()) - return SemaRef.StmtError(); + OwningExprResult Cond(SemaRef); + VarDecl *ConditionVar = 0; + if (S->getConditionVariable()) { + ConditionVar + = cast_or_null<VarDecl>( + getDerived().TransformDefinition(S->getConditionVariable())); + if (!ConditionVar) + return SemaRef.StmtError(); + } else { + Cond = getDerived().TransformExpr(S->getCond()); + + if (Cond.isInvalid()) + return SemaRef.StmtError(); + } Sema::FullExprArg FullCond(getSema().FullExpr(Cond)); @@ -3169,10 +3131,12 @@ TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) { if (!getDerived().AlwaysRebuild() && FullCond->get() == S->getCond() && + ConditionVar == S->getConditionVariable() && Body.get() == S->getBody()) return SemaRef.Owned(S->Retain()); - return getDerived().RebuildWhileStmt(S->getWhileLoc(), FullCond, move(Body)); + return getDerived().RebuildWhileStmt(S->getWhileLoc(), FullCond, ConditionVar, + move(Body)); } template<typename Derived> @@ -3207,9 +3171,20 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) { return SemaRef.StmtError(); // Transform the condition - OwningExprResult Cond = getDerived().TransformExpr(S->getCond()); - if (Cond.isInvalid()) - return SemaRef.StmtError(); + OwningExprResult Cond(SemaRef); + VarDecl *ConditionVar = 0; + if (S->getConditionVariable()) { + ConditionVar + = cast_or_null<VarDecl>( + getDerived().TransformDefinition(S->getConditionVariable())); + if (!ConditionVar) + return SemaRef.StmtError(); + } else { + Cond = getDerived().TransformExpr(S->getCond()); + + if (Cond.isInvalid()) + return SemaRef.StmtError(); + } // Transform the increment OwningExprResult Inc = getDerived().TransformExpr(S->getInc()); @@ -3229,7 +3204,9 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) { return SemaRef.Owned(S->Retain()); return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(), - move(Init), move(Cond), move(Inc), + move(Init), getSema().FullExpr(Cond), + ConditionVar, + getSema().FullExpr(Inc), S->getRParenLoc(), move(Body)); } @@ -3695,13 +3672,15 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E, !E->hasExplicitTemplateArgumentList()) return SemaRef.Owned(E->Retain()); - llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs; + TemplateArgumentListInfo TransArgs; if (E->hasExplicitTemplateArgumentList()) { - TransArgs.resize(E->getNumTemplateArgs()); + TransArgs.setLAngleLoc(E->getLAngleLoc()); + TransArgs.setRAngleLoc(E->getRAngleLoc()); for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) { - if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], - TransArgs[I])) + TemplateArgumentLoc Loc; + if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], Loc)) return SemaRef.ExprError(); + TransArgs.addArgument(Loc); } } @@ -3715,11 +3694,8 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E, E->getQualifierRange(), E->getMemberLoc(), Member, - E->hasExplicitTemplateArgumentList(), - E->getLAngleLoc(), - TransArgs.data(), - TransArgs.size(), - E->getRAngleLoc(), + (E->hasExplicitTemplateArgumentList() + ? &TransArgs : 0), 0); } @@ -4425,24 +4401,6 @@ TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E, template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E, - bool isAddressOfOperand) { - VarDecl *Var - = cast_or_null<VarDecl>(getDerived().TransformDefinition(E->getVarDecl())); - if (!Var) - return SemaRef.ExprError(); - - if (!getDerived().AlwaysRebuild() && - Var == E->getVarDecl()) - return SemaRef.Owned(E->Retain()); - - return getDerived().RebuildCXXConditionDeclExpr(E->getStartLoc(), - /*FIXME:*/E->getStartLoc(), - Var); -} - -template<typename Derived> -Sema::OwningExprResult TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E, bool isAddressOfOperand) { // Transform the type that we're allocating @@ -4558,11 +4516,66 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr( template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformUnresolvedFunctionNameExpr( - UnresolvedFunctionNameExpr *E, +TreeTransform<Derived>::TransformUnresolvedLookupExpr( + UnresolvedLookupExpr *Old, bool isAddressOfOperand) { - // There is no transformation we can apply to an unresolved function name. - return SemaRef.Owned(E->Retain()); + TemporaryBase Rebase(*this, Old->getNameLoc(), DeclarationName()); + + LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(), + Sema::LookupOrdinaryName); + + // Transform all the decls. + for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(), + E = Old->decls_end(); I != E; ++I) { + NamedDecl *InstD = static_cast<NamedDecl*>(getDerived().TransformDecl(*I)); + if (!InstD) + return SemaRef.ExprError(); + + // Expand using declarations. + if (isa<UsingDecl>(InstD)) { + UsingDecl *UD = cast<UsingDecl>(InstD); + for (UsingDecl::shadow_iterator I = UD->shadow_begin(), + E = UD->shadow_end(); I != E; ++I) + R.addDecl(*I); + continue; + } + + R.addDecl(InstD); + } + + // Resolve a kind, but don't do any further analysis. If it's + // ambiguous, the callee needs to deal with it. + R.resolveKind(); + + // Rebuild the nested-name qualifier, if present. + CXXScopeSpec SS; + NestedNameSpecifier *Qualifier = 0; + if (Old->getQualifier()) { + Qualifier = getDerived().TransformNestedNameSpecifier(Old->getQualifier(), + Old->getQualifierRange()); + if (!Qualifier) + return SemaRef.ExprError(); + + SS.setScopeRep(Qualifier); + SS.setRange(Old->getQualifierRange()); + } + + // If we have no template arguments, it's a normal declaration name. + if (!Old->hasExplicitTemplateArgs()) + return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); + + // If we have template arguments, rebuild them, then rebuild the + // templateid expression. + TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), Old->getRAngleLoc()); + for (unsigned I = 0, N = Old->getNumTemplateArgs(); I != N; ++I) { + TemplateArgumentLoc Loc; + if (getDerived().TransformTemplateArgument(Old->getTemplateArgs()[I], Loc)) + return SemaRef.ExprError(); + TransArgs.addArgument(Loc); + } + + return getDerived().RebuildTemplateIdExpr(SS, R, Old->requiresADL(), + TransArgs); } template<typename Derived> @@ -4592,8 +4605,8 @@ TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E, template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformUnresolvedDeclRefExpr( - UnresolvedDeclRefExpr *E, +TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( + DependentScopeDeclRefExpr *E, bool isAddressOfOperand) { NestedNameSpecifier *NNS = getDerived().TransformNestedNameSpecifier(E->getQualifier(), @@ -4606,56 +4619,30 @@ TreeTransform<Derived>::TransformUnresolvedDeclRefExpr( if (!Name) return SemaRef.ExprError(); - if (!getDerived().AlwaysRebuild() && - NNS == E->getQualifier() && - Name == E->getDeclName()) - return SemaRef.Owned(E->Retain()); - - return getDerived().RebuildUnresolvedDeclRefExpr(NNS, - E->getQualifierRange(), - Name, - E->getLocation(), - isAddressOfOperand); -} - -template<typename Derived> -Sema::OwningExprResult -TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E, - bool isAddressOfOperand) { - TemporaryBase Rebase(*this, E->getTemplateNameLoc(), DeclarationName()); - - TemplateName Template - = getDerived().TransformTemplateName(E->getTemplateName()); - if (Template.isNull()) - return SemaRef.ExprError(); + if (!E->hasExplicitTemplateArgs()) { + if (!getDerived().AlwaysRebuild() && + NNS == E->getQualifier() && + Name == E->getDeclName()) + return SemaRef.Owned(E->Retain()); - NestedNameSpecifier *Qualifier = 0; - if (E->getQualifier()) { - Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange()); - if (!Qualifier) - return SemaRef.ExprError(); + return getDerived().RebuildDependentScopeDeclRefExpr(NNS, + E->getQualifierRange(), + Name, E->getLocation(), + /*TemplateArgs*/ 0); } - - llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs(E->getNumTemplateArgs()); + + TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc()); for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) { - if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], - TransArgs[I])) + TemplateArgumentLoc Loc; + if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], Loc)) return SemaRef.ExprError(); + TransArgs.addArgument(Loc); } - // FIXME: Would like to avoid rebuilding if nothing changed, but we can't - // compare template arguments (yet). - - // FIXME: It's possible that we'll find out now that the template name - // actually refers to a type, in which case the caller is actually dealing - // with a functional cast. Give a reasonable error message! - return getDerived().RebuildTemplateIdExpr(Qualifier, E->getQualifierRange(), - Template, E->getTemplateNameLoc(), - E->getLAngleLoc(), - TransArgs.data(), - TransArgs.size(), - E->getRAngleLoc()); + return getDerived().RebuildDependentScopeDeclRefExpr(NNS, + E->getQualifierRange(), + Name, E->getLocation(), + &TransArgs); } template<typename Derived> @@ -4828,8 +4815,8 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr( - CXXUnresolvedMemberExpr *E, +TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr( + CXXDependentScopeMemberExpr *E, bool isAddressOfOperand) { // Transform the base of the expression. OwningExprResult Base = getDerived().TransformExpr(E->getBase()); @@ -4878,52 +4865,99 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr( FirstQualifierInScope == E->getFirstQualifierFoundInScope()) return SemaRef.Owned(E->Retain()); - return getDerived().RebuildCXXUnresolvedMemberExpr(move(Base), + return getDerived().RebuildCXXDependentScopeMemberExpr(move(Base), E->isArrow(), E->getOperatorLoc(), Qualifier, E->getQualifierRange(), + FirstQualifierInScope, Name, E->getMemberLoc(), - FirstQualifierInScope); + /*TemplateArgs*/ 0); } - // FIXME: This is an ugly hack, which forces the same template name to - // be looked up multiple times. Yuck! - TemporaryBase Rebase(*this, E->getMemberLoc(), DeclarationName()); - TemplateName OrigTemplateName; - if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) - OrigTemplateName = SemaRef.Context.getDependentTemplateName(0, II); - else - OrigTemplateName - = SemaRef.Context.getDependentTemplateName(0, - Name.getCXXOverloadedOperator()); - - TemplateName Template - = getDerived().TransformTemplateName(OrigTemplateName, - QualType::getFromOpaquePtr(ObjectType)); - if (Template.isNull()) - return SemaRef.ExprError(); - - llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs(E->getNumTemplateArgs()); + TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc()); for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) { - if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], - TransArgs[I])) + TemplateArgumentLoc Loc; + if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], Loc)) return SemaRef.ExprError(); + TransArgs.addArgument(Loc); } - return getDerived().RebuildCXXUnresolvedMemberExpr(move(Base), + return getDerived().RebuildCXXDependentScopeMemberExpr(move(Base), E->isArrow(), E->getOperatorLoc(), Qualifier, E->getQualifierRange(), - Template, - E->getMemberLoc(), FirstQualifierInScope, - E->getLAngleLoc(), - TransArgs.data(), - TransArgs.size(), - E->getRAngleLoc()); + Name, + E->getMemberLoc(), + &TransArgs); +} + +template<typename Derived> +Sema::OwningExprResult +TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old, + bool isAddressOfOperand) { + // Transform the base of the expression. + OwningExprResult Base = getDerived().TransformExpr(Old->getBase()); + if (Base.isInvalid()) + return SemaRef.ExprError(); + + NestedNameSpecifier *Qualifier = 0; + if (Old->getQualifier()) { + Qualifier + = getDerived().TransformNestedNameSpecifier(Old->getQualifier(), + Old->getQualifierRange()); + if (Qualifier == 0) + return SemaRef.ExprError(); + } + + LookupResult R(SemaRef, Old->getMemberName(), Old->getMemberLoc(), + Sema::LookupOrdinaryName); + + // Transform all the decls. + for (UnresolvedMemberExpr::decls_iterator I = Old->decls_begin(), + E = Old->decls_end(); I != E; ++I) { + NamedDecl *InstD = static_cast<NamedDecl*>(getDerived().TransformDecl(*I)); + if (!InstD) + return SemaRef.ExprError(); + + // Expand using declarations. + if (isa<UsingDecl>(InstD)) { + UsingDecl *UD = cast<UsingDecl>(InstD); + for (UsingDecl::shadow_iterator I = UD->shadow_begin(), + E = UD->shadow_end(); I != E; ++I) + R.addDecl(*I); + continue; + } + + R.addDecl(InstD); + } + + R.resolveKind(); + + TemplateArgumentListInfo TransArgs; + if (Old->hasExplicitTemplateArgs()) { + TransArgs.setLAngleLoc(Old->getLAngleLoc()); + TransArgs.setRAngleLoc(Old->getRAngleLoc()); + for (unsigned I = 0, N = Old->getNumTemplateArgs(); I != N; ++I) { + TemplateArgumentLoc Loc; + if (getDerived().TransformTemplateArgument(Old->getTemplateArgs()[I], + Loc)) + return SemaRef.ExprError(); + TransArgs.addArgument(Loc); + } + } + + return getDerived().RebuildUnresolvedMemberExpr(move(Base), + Old->getOperatorLoc(), + Old->isArrow(), + Qualifier, + Old->getQualifierRange(), + R, + (Old->hasExplicitTemplateArgs() + ? &TransArgs : 0)); } template<typename Derived> @@ -5266,12 +5300,8 @@ template<typename Derived> QualType TreeTransform<Derived>::RebuildTemplateSpecializationType( TemplateName Template, SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *Args, - unsigned NumArgs, - SourceLocation RAngleLoc) { - return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, LAngleLoc, - Args, NumArgs, RAngleLoc); + const TemplateArgumentListInfo &TemplateArgs) { + return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs); } template<typename Derived> @@ -5280,7 +5310,7 @@ TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, SourceRange Range, IdentifierInfo &II, QualType ObjectType, - NamedDecl *FirstQualifierInScope) { + NamedDecl *FirstQualifierInScope) { CXXScopeSpec SS; // FIXME: The source location information is all wrong. SS.setRange(Range); @@ -5330,14 +5360,6 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, template<typename Derived> TemplateName TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, - bool TemplateKW, - OverloadedFunctionDecl *Ovl) { - return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW, Ovl); -} - -template<typename Derived> -TemplateName -TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, const IdentifierInfo &II, QualType ObjectType) { CXXScopeSpec SS; @@ -5349,7 +5371,8 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, /*FIXME:*/getDerived().getBaseLocation(), SS, Name, - ObjectType.getAsOpaquePtr()) + ObjectType.getAsOpaquePtr(), + /*EnteringContext=*/false) .template getAsVal<TemplateName>(); } @@ -5369,7 +5392,8 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, /*FIXME:*/getDerived().getBaseLocation(), SS, Name, - ObjectType.getAsOpaquePtr()) + ObjectType.getAsOpaquePtr(), + /*EnteringContext=*/false) .template getAsVal<TemplateName>(); } @@ -5382,8 +5406,7 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, ExprArg Second) { Expr *FirstExpr = (Expr *)First.get(); Expr *SecondExpr = (Expr *)Second.get(); - DeclRefExpr *DRE - = cast<DeclRefExpr>(((Expr *)Callee.get())->IgnoreParenCasts()); + Expr *CalleeExpr = ((Expr *)Callee.get())->IgnoreParenCasts(); bool isPostIncDec = SecondExpr && (Op == OO_PlusPlus || Op == OO_MinusMinus); // Determine whether this should be a builtin operation. @@ -5391,7 +5414,7 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, if (!FirstExpr->getType()->isOverloadableType() && !SecondExpr->getType()->isOverloadableType()) return getSema().CreateBuiltinArraySubscriptExpr(move(First), - DRE->getLocStart(), + CalleeExpr->getLocStart(), move(Second), OpLoc); } else if (Op == OO_Arrow) { // -> is never a builtin operation. @@ -5426,10 +5449,18 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, // used during overload resolution. Sema::FunctionSet Functions; - // FIXME: Do we have to check - // IsAcceptableNonMemberOperatorCandidate for each of these? - for (OverloadIterator F(DRE->getDecl()), FEnd; F != FEnd; ++F) - Functions.insert(*F); + if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(CalleeExpr)) { + assert(ULE->requiresADL()); + + // FIXME: Do we have to check + // IsAcceptableNonMemberOperatorCandidate for each of these? + for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(), + E = ULE->decls_end(); I != E; ++I) + Functions.insert(AnyFunctionDecl::getFromNamedDecl(*I)); + } else { + Functions.insert(AnyFunctionDecl::getFromNamedDecl( + cast<DeclRefExpr>(CalleeExpr)->getDecl())); + } // Add any functions found via argument-dependent lookup. Expr *Args[2] = { FirstExpr, SecondExpr }; @@ -5447,8 +5478,10 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, } if (Op == OO_Subscript) - return SemaRef.CreateOverloadedArraySubscriptExpr(DRE->getLocStart(), OpLoc, - move(First),move(Second)); + return SemaRef.CreateOverloadedArraySubscriptExpr(CalleeExpr->getLocStart(), + OpLoc, + move(First), + move(Second)); // Create the overloaded operator invocation for binary operators. BinaryOperator::Opcode Opc = |