diff options
Diffstat (limited to 'lib/Sema')
29 files changed, 4610 insertions, 1933 deletions
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index 9b24d55..88ac4e4 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -16,28 +16,79 @@ #include "clang/Lex/Preprocessor.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> #include <functional> + using namespace clang; +using llvm::StringRef; //===----------------------------------------------------------------------===// // Code completion string implementation //===----------------------------------------------------------------------===// -CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) - : Kind(Kind), Text(0) +CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text) + : Kind(Kind), Text("") { - assert((Kind == CK_Text || Kind == CK_Placeholder || Kind == CK_Informative) - && "Invalid text chunk kind"); - char *New = new char [std::strlen(Text) + 1]; - std::strcpy(New, Text); - this->Text = New; + switch (Kind) { + case CK_TypedText: + case CK_Text: + case CK_Placeholder: + case CK_Informative: + case CK_CurrentParameter: { + char *New = new char [Text.size() + 1]; + std::memcpy(New, Text.data(), Text.size()); + New[Text.size()] = '\0'; + this->Text = New; + break; + } + + case CK_Optional: + llvm::llvm_unreachable("Optional strings cannot be created from text"); + break; + + case CK_LeftParen: + this->Text = "("; + break; + + case CK_RightParen: + this->Text = ")"; + break; + + case CK_LeftBracket: + this->Text = "["; + break; + + case CK_RightBracket: + this->Text = "]"; + break; + + case CK_LeftBrace: + this->Text = "{"; + break; + + case CK_RightBrace: + this->Text = "}"; + break; + + case CK_LeftAngle: + this->Text = "<"; + break; + + case CK_RightAngle: + this->Text = ">"; + break; + + case CK_Comma: + this->Text = ", "; + break; + } } CodeCompletionString::Chunk -CodeCompletionString::Chunk::CreateText(const char *Text) { +CodeCompletionString::Chunk::CreateText(StringRef Text) { return Chunk(CK_Text, Text); } @@ -51,15 +102,22 @@ CodeCompletionString::Chunk::CreateOptional( } CodeCompletionString::Chunk -CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) { +CodeCompletionString::Chunk::CreatePlaceholder(StringRef Placeholder) { return Chunk(CK_Placeholder, Placeholder); } CodeCompletionString::Chunk -CodeCompletionString::Chunk::CreateInformative(const char *Informative) { +CodeCompletionString::Chunk::CreateInformative(StringRef Informative) { return Chunk(CK_Informative, Informative); } +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateCurrentParameter( + StringRef CurrentParameter) { + return Chunk(CK_CurrentParameter, CurrentParameter); +} + + void CodeCompletionString::Chunk::Destroy() { switch (Kind) { @@ -67,10 +125,23 @@ CodeCompletionString::Chunk::Destroy() { delete Optional; break; + case CK_TypedText: case CK_Text: case CK_Placeholder: case CK_Informative: - delete [] Text; + case CK_CurrentParameter: + delete [] Text; + 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: break; } } @@ -86,16 +157,322 @@ std::string CodeCompletionString::getAsString() const { for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { switch (C->Kind) { - case CK_Text: OS << C->Text; break; case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; case CK_Informative: OS << "[#" << C->Text << "#]"; break; + case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break; + default: OS << C->Text; break; } } OS.flush(); 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); + + // 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(); + } +} + +void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const { + for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { + 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) << "</>"; + break; + case CK_CurrentParameter: + OS << "<current-parameter>" << EscapedString(C->Text) << "</>"; + 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(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) + 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) + 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)); + Result->AddOptionalChunk(Optional); + } + + 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; + } + } + + // Remove this tag. + Str = Str.substr(AfterTag); + } while (!Str.empty()); + + return Result; +} + //===----------------------------------------------------------------------===// // Code completion overload candidate implementation //===----------------------------------------------------------------------===// @@ -133,7 +510,8 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { CodeCompleteConsumer::~CodeCompleteConsumer() { } void -PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results, +PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, + Result *Results, unsigned NumResults) { // Print the results. for (unsigned I = 0; I != NumResults; ++I) { @@ -177,7 +555,8 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results, } void -PrintingCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg, +PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, + unsigned CurrentArg, OverloadCandidate *Candidates, unsigned NumCandidates) { for (unsigned I = 0; I != NumCandidates; ++I) { @@ -193,3 +572,87 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg, // FIXME: Move this somewhere else! SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); } + +void +CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, + Result *Results, + unsigned NumResults) { + // Print the results. + for (unsigned I = 0; I != NumResults; ++I) { + OS << "COMPLETION:" << Results[I].Rank << ":"; + 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() + << "</>"; + } + + OS << '\n'; + break; + + case Result::RK_Keyword: + OS << "Keyword:<typed-text>" << Results[I].Keyword << "</>\n"; + 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'; + break; + } + } + } + + // Once we've printed the code-completion results, suppress remaining + // diagnostics. + // FIXME: Move this somewhere else! + SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); +} + +void +CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, + unsigned CurrentArg, + 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; + } + } + + // Once we've printed the code-completion results, suppress remaining + // diagnostics. + // FIXME: Move this somewhere else! + SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); +} diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index a8e31d2..2b37e9d 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -325,5 +325,5 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, } void Sema::DiagnoseInvalidJumps(Stmt *Body) { - JumpScopeChecker(Body, *this); + (void)JumpScopeChecker(Body, *this); } diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h new file mode 100644 index 0000000..6e72dce --- /dev/null +++ b/lib/Sema/Lookup.h @@ -0,0 +1,392 @@ +//===--- Lookup.h - Classes for name lookup ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the LookupResult class, which is integral to +// Sema's name-lookup subsystem. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_LOOKUP_H +#define LLVM_CLANG_SEMA_LOOKUP_H + +#include "Sema.h" + +namespace clang { + +/// @brief Represents the results of name lookup. +/// +/// An instance of the LookupResult class captures the results of a +/// single name lookup, which can return no result (nothing found), +/// a single declaration, a set of overloaded functions, or an +/// ambiguity. Use the getKind() method to determine which of these +/// results occurred for a given lookup. +/// +/// Any non-ambiguous lookup can be converted into a single +/// (possibly NULL) @c NamedDecl* via the getAsSingleDecl() method. +/// This permits the common-case usage in C and Objective-C where +/// name lookup will always return a single declaration. Use of +/// this is largely deprecated; callers should handle the possibility +/// of multiple declarations. +class LookupResult { +public: + enum LookupResultKind { + /// @brief No entity found met the criteria. + NotFound = 0, + + /// @brief Name lookup found a single declaration that met the + /// criteria. getAsDecl will return this declaration. + Found, + + /// @brief Name lookup found a set of overloaded functions that + /// met the criteria. getAsDecl will turn this set of overloaded + /// functions into an OverloadedFunctionDecl. + FoundOverloaded, + + /// @brief Name lookup found an unresolvable value declaration + /// and cannot yet complete. This only happens in C++ dependent + /// contexts with dependent using declarations. + FoundUnresolvedValue, + + /// @brief Name lookup results in an ambiguity; use + /// getAmbiguityKind to figure out what kind of ambiguity + /// we have. + Ambiguous + }; + + enum AmbiguityKind { + /// Name lookup results in an ambiguity because multiple + /// entities that meet the lookup criteria were found in + /// subobjects of different types. For example: + /// @code + /// struct A { void f(int); } + /// struct B { void f(double); } + /// struct C : A, B { }; + /// void test(C c) { + /// c.f(0); // error: A::f and B::f come from subobjects of different + /// // types. overload resolution is not performed. + /// } + /// @endcode + AmbiguousBaseSubobjectTypes, + + /// Name lookup results in an ambiguity because multiple + /// nonstatic entities that meet the lookup criteria were found + /// in different subobjects of the same type. For example: + /// @code + /// struct A { int x; }; + /// struct B : A { }; + /// struct C : A { }; + /// struct D : B, C { }; + /// int test(D d) { + /// return d.x; // error: 'x' is found in two A subobjects (of B and C) + /// } + /// @endcode + AmbiguousBaseSubobjects, + + /// Name lookup results in an ambiguity because multiple definitions + /// of entity that meet the lookup criteria were found in different + /// declaration contexts. + /// @code + /// namespace A { + /// int i; + /// namespace B { int i; } + /// int test() { + /// using namespace B; + /// return i; // error 'i' is found in namespace A and A::B + /// } + /// } + /// @endcode + AmbiguousReference, + + /// Name lookup results in an ambiguity because an entity with a + /// tag name was hidden by an entity with an ordinary name from + /// a different context. + /// @code + /// namespace A { struct Foo {}; } + /// namespace B { void Foo(); } + /// namespace C { + /// using namespace A; + /// using namespace B; + /// } + /// void test() { + /// C::Foo(); // error: tag 'A::Foo' is hidden by an object in a + /// // different namespace + /// } + /// @endcode + AmbiguousTagHiding + }; + + /// A little identifier for flagging temporary lookup results. + enum TemporaryToken { + Temporary + }; + + typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy; + typedef DeclsTy::const_iterator iterator; + + LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc, + Sema::LookupNameKind LookupKind, + Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) + : ResultKind(NotFound), + Paths(0), + SemaRef(SemaRef), + Name(Name), + NameLoc(NameLoc), + LookupKind(LookupKind), + IDNS(0), + Redecl(Redecl != Sema::NotForRedeclaration), + HideTags(true), + Diagnose(Redecl == Sema::NotForRedeclaration) + {} + + /// Creates a temporary lookup result, initializing its core data + /// using the information from another result. Diagnostics are always + /// disabled. + LookupResult(TemporaryToken _, const LookupResult &Other) + : ResultKind(NotFound), + Paths(0), + SemaRef(Other.SemaRef), + Name(Other.Name), + NameLoc(Other.NameLoc), + LookupKind(Other.LookupKind), + IDNS(Other.IDNS), + Redecl(Other.Redecl), + HideTags(Other.HideTags), + Diagnose(false) + {} + + ~LookupResult() { + if (Diagnose) diagnose(); + if (Paths) deletePaths(Paths); + } + + /// Gets the name to look up. + DeclarationName getLookupName() const { + return Name; + } + + /// Gets the kind of lookup to perform. + Sema::LookupNameKind getLookupKind() const { + return LookupKind; + } + + /// True if this lookup is just looking for an existing declaration. + bool isForRedeclaration() const { + return Redecl; + } + + /// Sets whether tag declarations should be hidden by non-tag + /// declarations during resolution. The default is true. + void setHideTags(bool Hide) { + HideTags = Hide; + } + + /// The identifier namespace of this lookup. This information is + /// private to the lookup routines. + unsigned getIdentifierNamespace() const { + assert(IDNS); + return IDNS; + } + + void setIdentifierNamespace(unsigned NS) { + IDNS = NS; + } + + bool isAmbiguous() const { + return getResultKind() == Ambiguous; + } + + LookupResultKind getResultKind() const { + sanity(); + return ResultKind; + } + + AmbiguityKind getAmbiguityKind() const { + assert(isAmbiguous()); + return Ambiguity; + } + + iterator begin() const { return Decls.begin(); } + iterator end() const { return Decls.end(); } + + /// \brief Return true if no decls were found + bool empty() const { return Decls.empty(); } + + /// \brief Return the base paths structure that's associated with + /// these results, or null if none is. + CXXBasePaths *getBasePaths() const { + return Paths; + } + + /// \brief Add a declaration to these results. + void addDecl(NamedDecl *D) { + Decls.push_back(D); + ResultKind = Found; + } + + /// \brief Add all the declarations from another set of lookup + /// results. + void addAllDecls(const LookupResult &Other) { + Decls.append(Other.begin(), Other.end()); + ResultKind = Found; + } + + /// \brief Hides a set of declarations. + template <class NamedDeclSet> void hideDecls(const NamedDeclSet &Set) { + unsigned I = 0, N = Decls.size(); + while (I < N) { + if (Set.count(Decls[I])) + Decls[I] = Decls[--N]; + else + I++; + } + Decls.set_size(N); + } + + /// \brief Resolves the kind of the lookup, possibly hiding decls. + /// + /// This should be called in any environment where lookup might + /// generate multiple lookup results. + void resolveKind(); + + /// \brief Fetch this as an unambiguous single declaration + /// (possibly an overloaded one). + /// + /// This is deprecated; users should be written to handle + /// ambiguous and overloaded lookups. + NamedDecl *getAsSingleDecl(ASTContext &Context) const; + + /// \brief Fetch the unique decl found by this lookup. Asserts + /// that one was found. + /// + /// This is intended for users who have examined the result kind + /// and are certain that there is only one result. + NamedDecl *getFoundDecl() const { + assert(getResultKind() == Found + && "getFoundDecl called on non-unique result"); + return Decls[0]->getUnderlyingDecl(); + } + + /// \brief Asks if the result is a single tag decl. + bool isSingleTagDecl() const { + return getResultKind() == Found && isa<TagDecl>(getFoundDecl()); + } + + /// \brief Make these results show that the name was found in + /// base classes of different types. + /// + /// The given paths object is copied and invalidated. + void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P); + + /// \brief Make these results show that the name was found in + /// distinct base classes of the same type. + /// + /// The given paths object is copied and invalidated. + void setAmbiguousBaseSubobjects(CXXBasePaths &P); + + /// \brief Make these results show that the name was found in + /// different contexts and a tag decl was hidden by an ordinary + /// decl in a different context. + void setAmbiguousQualifiedTagHiding() { + setAmbiguous(AmbiguousTagHiding); + } + + /// \brief Clears out any current state. + void clear() { + ResultKind = NotFound; + Decls.clear(); + if (Paths) deletePaths(Paths); + Paths = NULL; + } + + /// \brief Clears out any current state and re-initializes for a + /// different kind of lookup. + void clear(Sema::LookupNameKind Kind) { + clear(); + LookupKind = Kind; + } + + void print(llvm::raw_ostream &); + + /// Suppress the diagnostics that would normally fire because of this + /// lookup. This happens during (e.g.) redeclaration lookups. + void suppressDiagnostics() { + Diagnose = false; + } + + /// Sets a 'context' source range. + void setContextRange(SourceRange SR) { + NameContextRange = SR; + } + + /// Gets the source range of the context of this name; for C++ + /// qualified lookups, this is the source range of the scope + /// specifier. + SourceRange getContextRange() const { + return NameContextRange; + } + + /// Gets the location of the identifier. This isn't always defined: + /// sometimes we're doing lookups on synthesized names. + SourceLocation getNameLoc() const { + return NameLoc; + } + +private: + void diagnose() { + if (isAmbiguous()) + SemaRef.DiagnoseAmbiguousLookup(*this); + } + + void setAmbiguous(AmbiguityKind AK) { + ResultKind = Ambiguous; + Ambiguity = AK; + } + + void addDeclsFromBasePaths(const CXXBasePaths &P); + + // Sanity checks. + 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((Paths != NULL) == (ResultKind == Ambiguous && + (Ambiguity == AmbiguousBaseSubobjectTypes || + Ambiguity == AmbiguousBaseSubobjects))); + } + + static void deletePaths(CXXBasePaths *); + + // Results. + LookupResultKind ResultKind; + AmbiguityKind Ambiguity; // ill-defined unless ambiguous + DeclsTy Decls; + CXXBasePaths *Paths; + + // Parameters. + Sema &SemaRef; + DeclarationName Name; + SourceLocation NameLoc; + SourceRange NameContextRange; + Sema::LookupNameKind LookupKind; + unsigned IDNS; // ill-defined until set by lookup + bool Redecl; + + /// \brief True if tag declarations should be hidden if non-tags + /// are present + bool HideTags; + + bool Diagnose; +}; + +} + +#endif diff --git a/lib/Sema/ParseAST.cpp b/lib/Sema/ParseAST.cpp index d3f26d8..7b223a8 100644 --- a/lib/Sema/ParseAST.cpp +++ b/lib/Sema/ParseAST.cpp @@ -35,15 +35,14 @@ using namespace clang; void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, ASTContext &Ctx, bool PrintStats, bool CompleteTranslationUnit, - CodeCompleteConsumer *(*CreateCodeCompleter)(Sema &, void *Data), - void *CreateCodeCompleterData) { + CodeCompleteConsumer *CompletionConsumer) { // Collect global stats on Decls/Stmts (until we have a module streamer). if (PrintStats) { Decl::CollectingStats(true); Stmt::CollectingStats(true); } - Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit); + Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit, CompletionConsumer); Parser P(PP, S); PP.EnterMainSourceFile(); @@ -63,12 +62,6 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, External->StartTranslationUnit(Consumer); } - CodeCompleteConsumer *CodeCompleter = 0; - if (CreateCodeCompleter) { - CodeCompleter = CreateCodeCompleter(S, CreateCodeCompleterData); - S.setCodeCompleteConsumer(CodeCompleter); - } - Parser::DeclGroupPtrTy ADecl; while (!P.ParseTopLevelDecl(ADecl)) { // Not end of file. @@ -78,6 +71,9 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, if (ADecl) Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>()); }; + // Check for any pending objective-c implementation decl. + while ((ADecl = P.RetrievePendingObjCImpDecl())) + Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>()); // process any TopLevelDecls generated by #pragma weak for (llvm::SmallVector<Decl*,2>::iterator @@ -87,9 +83,6 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, Consumer->HandleTranslationUnit(Ctx); - if (CreateCodeCompleter) - delete CodeCompleter; - if (PrintStats) { fprintf(stderr, "\nSTATISTICS:\n"); P.getActions().PrintStats(); diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 8104dd3..b2bbac8 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -14,6 +14,7 @@ #include "Sema.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/APFloat.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -346,16 +347,18 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { } Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, - bool CompleteTranslationUnit) + bool CompleteTranslationUnit, + CodeCompleteConsumer *CodeCompleter) : LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), - ExternalSource(0), CodeCompleter(0), CurContext(0), + 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), CompleteTranslationUnit(CompleteTranslationUnit), - NumSFINAEErrors(0), CurrentInstantiationScope(0) { - + NumSFINAEErrors(0), NonInstantiationEntries(0), + CurrentInstantiationScope(0) +{ TUScope = 0; if (getLangOptions().CPlusPlus) FieldCollector.reset(new CXXFieldCollector()); @@ -364,6 +367,322 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, PP.getDiagnostics().SetArgToStringFn(ConvertArgToStringFn, &Context); } +/// Retrieves the width and signedness of the given integer type, +/// or returns false if it is not an integer type. +/// +/// \param T must be canonical +static bool getIntProperties(ASTContext &C, const Type *T, + unsigned &BitWidth, bool &Signed) { + assert(T->isCanonicalUnqualified()); + + if (const VectorType *VT = dyn_cast<VectorType>(T)) + T = VT->getElementType().getTypePtr(); + if (const ComplexType *CT = dyn_cast<ComplexType>(T)) + T = CT->getElementType().getTypePtr(); + + if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) { + if (!BT->isInteger()) return false; + + BitWidth = C.getIntWidth(QualType(T, 0)); + Signed = BT->isSignedInteger(); + return true; + } + + if (const FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) { + BitWidth = FWIT->getWidth(); + Signed = FWIT->isSigned(); + return true; + } + + return false; +} + +/// Checks whether the given value will have the same value if it it +/// is truncated to the given width, then extended back to the +/// original width. +static bool IsSameIntAfterCast(const llvm::APSInt &value, + unsigned TargetWidth) { + unsigned SourceWidth = value.getBitWidth(); + llvm::APSInt truncated = value; + truncated.trunc(TargetWidth); + truncated.extend(SourceWidth); + return (truncated == value); +} + +/// Checks whether the given value will have the same value if it +/// is truncated to the given width, then extended back to the original +/// width. +/// +/// The value might be a vector or a complex. +static bool IsSameIntAfterCast(const APValue &value, unsigned TargetWidth) { + if (value.isInt()) + return IsSameIntAfterCast(value.getInt(), TargetWidth); + + if (value.isVector()) { + for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i) + if (!IsSameIntAfterCast(value.getVectorElt(i), TargetWidth)) + return false; + return true; + } + + if (value.isComplexInt()) { + return IsSameIntAfterCast(value.getComplexIntReal(), TargetWidth) && + IsSameIntAfterCast(value.getComplexIntImag(), TargetWidth); + } + + // This can happen with lossless casts to intptr_t of "based" lvalues. + // Assume it might use arbitrary bits. + assert(value.isLValue()); + return false; +} + + +/// Checks whether the given value, which currently has the given +/// source semantics, has the same value when coerced through the +/// target semantics. +static bool IsSameFloatAfterCast(const llvm::APFloat &value, + const llvm::fltSemantics &Src, + const llvm::fltSemantics &Tgt) { + llvm::APFloat truncated = value; + + bool ignored; + truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored); + truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored); + + return truncated.bitwiseIsEqual(value); +} + +/// Checks whether the given value, which currently has the given +/// source semantics, has the same value when coerced through the +/// target semantics. +/// +/// The value might be a vector of floats (or a complex number). +static bool IsSameFloatAfterCast(const APValue &value, + const llvm::fltSemantics &Src, + const llvm::fltSemantics &Tgt) { + if (value.isFloat()) + return IsSameFloatAfterCast(value.getFloat(), Src, Tgt); + + if (value.isVector()) { + for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i) + if (!IsSameFloatAfterCast(value.getVectorElt(i), Src, Tgt)) + return false; + return true; + } + + assert(value.isComplexFloat()); + return (IsSameFloatAfterCast(value.getComplexFloatReal(), Src, Tgt) && + IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt)); +} + +/// Determines if it's reasonable for the given expression to be truncated +/// down to the given integer width. +/// * Boolean expressions are automatically white-listed. +/// * Arithmetic operations on implicitly-promoted operands of the +/// target width or less are okay --- not because the results are +/// actually guaranteed to fit within the width, but because the +/// user is effectively pretending that the operations are closed +/// within the implicitly-promoted type. +static bool IsExprValueWithinWidth(ASTContext &C, Expr *E, unsigned Width) { + E = E->IgnoreParens(); + +#ifndef NDEBUG + { + const Type *ETy = E->getType()->getCanonicalTypeInternal().getTypePtr(); + unsigned EWidth; + bool ESigned; + + if (!getIntProperties(C, ETy, EWidth, ESigned)) + assert(0 && "expression not of integer type"); + + // The caller should never let this happen. + assert(EWidth > Width && "called on expr whose type is too small"); + } +#endif + + // Strip implicit casts off. + while (isa<ImplicitCastExpr>(E)) { + E = cast<ImplicitCastExpr>(E)->getSubExpr(); + + const Type *ETy = E->getType()->getCanonicalTypeInternal().getTypePtr(); + + unsigned EWidth; + bool ESigned; + if (!getIntProperties(C, ETy, EWidth, ESigned)) + return false; + + if (EWidth <= Width) + return true; + } + + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { + switch (BO->getOpcode()) { + + // Boolean-valued operations are white-listed. + case BinaryOperator::LAnd: + case BinaryOperator::LOr: + case BinaryOperator::LT: + case BinaryOperator::GT: + case BinaryOperator::LE: + case BinaryOperator::GE: + case BinaryOperator::EQ: + case BinaryOperator::NE: + return true; + + // Operations with opaque sources are black-listed. + case BinaryOperator::PtrMemD: + case BinaryOperator::PtrMemI: + return false; + + // Left shift gets black-listed based on a judgement call. + case BinaryOperator::Shl: + return false; + + // Various special cases. + case BinaryOperator::Shr: + return IsExprValueWithinWidth(C, BO->getLHS(), Width); + case BinaryOperator::Comma: + return IsExprValueWithinWidth(C, BO->getRHS(), Width); + case BinaryOperator::Sub: + if (BO->getLHS()->getType()->isPointerType()) + return false; + // fallthrough + + // Any other operator is okay if the operands are + // promoted from expressions of appropriate size. + default: + return IsExprValueWithinWidth(C, BO->getLHS(), Width) && + IsExprValueWithinWidth(C, BO->getRHS(), Width); + } + } + + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) { + switch (UO->getOpcode()) { + // Boolean-valued operations are white-listed. + case UnaryOperator::LNot: + return true; + + // Operations with opaque sources are black-listed. + case UnaryOperator::Deref: + case UnaryOperator::AddrOf: // should be impossible + return false; + + case UnaryOperator::OffsetOf: + return false; + + default: + return IsExprValueWithinWidth(C, UO->getSubExpr(), Width); + } + } + + // Don't diagnose if the expression is an integer constant + // whose value in the target type is the same as it was + // in the original type. + Expr::EvalResult result; + if (E->Evaluate(result, C)) + if (IsSameIntAfterCast(result.Val, Width)) + return true; + + return false; +} + +/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. +static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, unsigned diag) { + S.Diag(E->getExprLoc(), diag) << E->getType() << T << E->getSourceRange(); +} + +/// Implements -Wconversion. +static void CheckImplicitConversion(Sema &S, Expr *E, QualType T) { + // Don't diagnose in unevaluated contexts. + if (S.ExprEvalContext == Sema::Unevaluated) + return; + + // Don't diagnose for value-dependent expressions. + if (E->isValueDependent()) + return; + + const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr(); + const Type *Target = S.Context.getCanonicalType(T).getTypePtr(); + + // Never diagnose implicit casts to bool. + if (Target->isSpecificBuiltinType(BuiltinType::Bool)) + return; + + // Strip vector types. + if (isa<VectorType>(Source)) { + if (!isa<VectorType>(Target)) + return DiagnoseImpCast(S, E, T, diag::warn_impcast_vector_scalar); + + Source = cast<VectorType>(Source)->getElementType().getTypePtr(); + Target = cast<VectorType>(Target)->getElementType().getTypePtr(); + } + + // Strip complex types. + if (isa<ComplexType>(Source)) { + if (!isa<ComplexType>(Target)) + return DiagnoseImpCast(S, E, T, diag::warn_impcast_complex_scalar); + + Source = cast<ComplexType>(Source)->getElementType().getTypePtr(); + Target = cast<ComplexType>(Target)->getElementType().getTypePtr(); + } + + const BuiltinType *SourceBT = dyn_cast<BuiltinType>(Source); + const BuiltinType *TargetBT = dyn_cast<BuiltinType>(Target); + + // If the source is floating point... + if (SourceBT && SourceBT->isFloatingPoint()) { + // ...and the target is floating point... + if (TargetBT && TargetBT->isFloatingPoint()) { + // ...then warn if we're dropping FP rank. + + // Builtin FP kinds are ordered by increasing FP rank. + if (SourceBT->getKind() > TargetBT->getKind()) { + // Don't warn about float constants that are precisely + // representable in the target type. + Expr::EvalResult result; + if (E->Evaluate(result, S.Context)) { + // Value might be a float, a float vector, or a float complex. + if (IsSameFloatAfterCast(result.Val, + S.Context.getFloatTypeSemantics(QualType(TargetBT, 0)), + S.Context.getFloatTypeSemantics(QualType(SourceBT, 0)))) + return; + } + + DiagnoseImpCast(S, E, T, diag::warn_impcast_float_precision); + } + return; + } + + // If the target is integral, always warn. + if ((TargetBT && TargetBT->isInteger()) || + isa<FixedWidthIntType>(Target)) + // TODO: don't warn for integer values? + return DiagnoseImpCast(S, E, T, diag::warn_impcast_float_integer); + + return; + } + + unsigned SourceWidth, TargetWidth; + bool SourceSigned, TargetSigned; + + if (!getIntProperties(S.Context, Source, SourceWidth, SourceSigned) || + !getIntProperties(S.Context, Target, TargetWidth, TargetSigned)) + return; + + if (SourceWidth > TargetWidth) { + if (IsExprValueWithinWidth(S.Context, E, TargetWidth)) + return; + + // People want to build with -Wshorten-64-to-32 and not -Wconversion + // and by god we'll let them. + if (SourceWidth == 64 && TargetWidth == 32) + return DiagnoseImpCast(S, E, T, diag::warn_impcast_integer_64_32); + return DiagnoseImpCast(S, E, T, diag::warn_impcast_integer_precision); + } + + return; +} + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. /// If there is already an implicit cast, merge into the existing one. /// If isLvalue, the result of the cast is an lvalue. @@ -375,18 +694,17 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, if (ExprTy == TypeTy) return; - if (Expr->getType().getTypePtr()->isPointerType() && - Ty.getTypePtr()->isPointerType()) { - QualType ExprBaseType = - cast<PointerType>(ExprTy.getUnqualifiedType())->getPointeeType(); - QualType BaseType = - cast<PointerType>(TypeTy.getUnqualifiedType())->getPointeeType(); + if (Expr->getType()->isPointerType() && Ty->isPointerType()) { + QualType ExprBaseType = cast<PointerType>(ExprTy)->getPointeeType(); + QualType BaseType = cast<PointerType>(TypeTy)->getPointeeType(); if (ExprBaseType.getAddressSpace() != BaseType.getAddressSpace()) { Diag(Expr->getExprLoc(), diag::err_implicit_pointer_address_space_cast) << Expr->getSourceRange(); } } + CheckImplicitConversion(*this, Expr, Ty); + if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) { if (ImpCast->getCastKind() == Kind) { ImpCast->setType(Ty); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index c4de6be..3e186b2 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -93,6 +93,7 @@ namespace clang { class FunctionProtoType; class CXXBasePaths; class CXXTemporary; + class LookupResult; /// BlockSemaInfo - When a block is being parsed, this contains information /// about the block. It is pointed to from Sema::CurBlock. @@ -373,7 +374,8 @@ public: bool isSelfExpr(Expr *RExpr); public: Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, - bool CompleteTranslationUnit = true); + bool CompleteTranslationUnit = true, + CodeCompleteConsumer *CompletionConsumer = 0); ~Sema() { if (PackContext) FreePackedContext(); } @@ -804,13 +806,15 @@ public: QualType& ConvertedType, bool &IncompatibleObjC); bool isObjCPointerConversion(QualType FromType, QualType ToType, QualType& ConvertedType, bool &IncompatibleObjC); - bool CheckPointerConversion(Expr *From, QualType ToType, - CastExpr::CastKind &Kind); + bool CheckPointerConversion(Expr *From, QualType ToType, + CastExpr::CastKind &Kind, + bool IgnoreBaseAccess); bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType, bool InOverloadResolution, QualType &ConvertedType); bool CheckMemberPointerConversion(Expr *From, QualType ToType, - CastExpr::CastKind &Kind); + CastExpr::CastKind &Kind, + bool IgnoreBaseAccess); bool IsQualificationConversion(QualType FromType, QualType ToType); OverloadingResult IsUserDefinedConversion(Expr *From, QualType ToType, UserDefinedConversionSequence& User, @@ -870,6 +874,11 @@ public: Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false); + void AddMethodCandidate(NamedDecl *Decl, + Expr *Object, Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversion = false, + bool ForceRValue = false); void AddMethodCandidate(CXXMethodDecl *Method, Expr *Object, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, @@ -1073,255 +1082,14 @@ public: LookupObjCCategoryImplName }; - /// @brief Represents the results of name lookup. - /// - /// An instance of the LookupResult class captures the results of a - /// single name lookup, which can return no result (nothing found), - /// a single declaration, a set of overloaded functions, or an - /// ambiguity. Use the getKind() method to determine which of these - /// results occurred for a given lookup. - /// - /// Any non-ambiguous lookup can be converted into a single - /// (possibly NULL) @c NamedDecl* via the getAsSingleDecl() method. - /// This permits the common-case usage in C and Objective-C where - /// name lookup will always return a single declaration. Use of - /// this is largely deprecated; callers should handle the possibility - /// of multiple declarations. - class LookupResult { - public: - enum LookupKind { - /// @brief No entity found met the criteria. - NotFound = 0, - - /// @brief Name lookup found a single declaration that met the - /// criteria. getAsDecl will return this declaration. - Found, - - /// @brief Name lookup found a set of overloaded functions that - /// met the criteria. getAsDecl will turn this set of overloaded - /// functions into an OverloadedFunctionDecl. - FoundOverloaded, - - /// @brief Name lookup results in an ambiguity; use - /// getAmbiguityKind to figure out what kind of ambiguity - /// we have. - Ambiguous - }; - - enum AmbiguityKind { - /// Name lookup results in an ambiguity because multiple - /// entities that meet the lookup criteria were found in - /// subobjects of different types. For example: - /// @code - /// struct A { void f(int); } - /// struct B { void f(double); } - /// struct C : A, B { }; - /// void test(C c) { - /// c.f(0); // error: A::f and B::f come from subobjects of different - /// // types. overload resolution is not performed. - /// } - /// @endcode - AmbiguousBaseSubobjectTypes, - - /// Name lookup results in an ambiguity because multiple - /// nonstatic entities that meet the lookup criteria were found - /// in different subobjects of the same type. For example: - /// @code - /// struct A { int x; }; - /// struct B : A { }; - /// struct C : A { }; - /// struct D : B, C { }; - /// int test(D d) { - /// return d.x; // error: 'x' is found in two A subobjects (of B and C) - /// } - /// @endcode - AmbiguousBaseSubobjects, - - /// Name lookup results in an ambiguity because multiple definitions - /// of entity that meet the lookup criteria were found in different - /// declaration contexts. - /// @code - /// namespace A { - /// int i; - /// namespace B { int i; } - /// int test() { - /// using namespace B; - /// return i; // error 'i' is found in namespace A and A::B - /// } - /// } - /// @endcode - AmbiguousReference, - - /// Name lookup results in an ambiguity because an entity with a - /// tag name was hidden by an entity with an ordinary name from - /// a different context. - /// @code - /// namespace A { struct Foo {}; } - /// namespace B { void Foo(); } - /// namespace C { - /// using namespace A; - /// using namespace B; - /// } - /// void test() { - /// C::Foo(); // error: tag 'A::Foo' is hidden by an object in a - /// // different namespace - /// } - /// @endcode - AmbiguousTagHiding - }; - - typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy; - typedef DeclsTy::const_iterator iterator; - - LookupResult() - : Kind(NotFound), - Paths(0) - {} - ~LookupResult() { - if (Paths) deletePaths(Paths); - } - - bool isAmbiguous() const { - return getKind() == Ambiguous; - } - - LookupKind getKind() const { - sanity(); - return Kind; - } - - AmbiguityKind getAmbiguityKind() const { - assert(isAmbiguous()); - return Ambiguity; - } - - iterator begin() const { return Decls.begin(); } - iterator end() const { return Decls.end(); } - - /// \brief Return true if no decls were found - bool empty() const { return Decls.empty(); } - - /// \brief Return the base paths structure that's associated with - /// these results, or null if none is. - CXXBasePaths *getBasePaths() const { - return Paths; - } - - /// \brief Add a declaration to these results. - void addDecl(NamedDecl *D) { - Decls.push_back(D->getUnderlyingDecl()); - Kind = Found; - } - - /// \brief Add all the declarations from another set of lookup - /// results. - void addAllDecls(const LookupResult &Other) { - Decls.append(Other.begin(), Other.end()); - Kind = Found; - } - - /// \brief Hides a set of declarations. - template <class NamedDeclSet> void hideDecls(const NamedDeclSet &Set) { - unsigned I = 0, N = Decls.size(); - while (I < N) { - if (Set.count(Decls[I])) - Decls[I] = Decls[--N]; - else - I++; - } - Decls.set_size(N); - } - - /// \brief Resolves the kind of the lookup, possibly hiding decls. - /// - /// This should be called in any environment where lookup might - /// generate multiple lookup results. - void resolveKind(); - - /// \brief Fetch this as an unambiguous single declaration - /// (possibly an overloaded one). - /// - /// This is deprecated; users should be written to handle - /// ambiguous and overloaded lookups. - NamedDecl *getAsSingleDecl(ASTContext &Context) const; - - /// \brief Fetch the unique decl found by this lookup. Asserts - /// that one was found. - /// - /// This is intended for users who have examined the result kind - /// and are certain that there is only one result. - NamedDecl *getFoundDecl() const { - assert(getKind() == Found && "getFoundDecl called on non-unique result"); - return *Decls.begin(); - } - - /// \brief Asks if the result is a single tag decl. - bool isSingleTagDecl() const { - return getKind() == Found && isa<TagDecl>(getFoundDecl()); - } - - /// \brief Make these results show that the name was found in - /// base classes of different types. - /// - /// The given paths object is copied and invalidated. - void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P); - - /// \brief Make these results show that the name was found in - /// distinct base classes of the same type. - /// - /// The given paths object is copied and invalidated. - void setAmbiguousBaseSubobjects(CXXBasePaths &P); - - /// \brief Make these results show that the name was found in - /// different contexts and a tag decl was hidden by an ordinary - /// decl in a different context. - void setAmbiguousQualifiedTagHiding() { - setAmbiguous(AmbiguousTagHiding); - } - - /// \brief Clears out any current state. - void clear() { - Kind = NotFound; - Decls.clear(); - if (Paths) deletePaths(Paths); - Paths = NULL; - } - - void print(llvm::raw_ostream &); - - private: - void setAmbiguous(AmbiguityKind AK) { - Kind = Ambiguous; - Ambiguity = AK; - } - - void addDeclsFromBasePaths(const CXXBasePaths &P); - - // Sanity checks. - void sanity() const { - assert(Kind != NotFound || Decls.size() == 0); - assert(Kind != Found || Decls.size() == 1); - assert(Kind == NotFound || Kind == Found || - (Kind == Ambiguous && Ambiguity == AmbiguousBaseSubobjects) - || Decls.size() > 1); - assert((Paths != NULL) == (Kind == Ambiguous && - (Ambiguity == AmbiguousBaseSubobjectTypes || - Ambiguity == AmbiguousBaseSubobjects))); - } - - static void deletePaths(CXXBasePaths *); - - LookupKind Kind; - AmbiguityKind Ambiguity; // ill-defined unless ambiguous - DeclsTy Decls; - CXXBasePaths *Paths; + enum RedeclarationKind { + NotForRedeclaration, + ForRedeclaration }; private: - typedef llvm::SmallVector<LookupResult, 3> LookupResultsVecTy; + bool CppLookupName(LookupResult &R, Scope *S); - bool CppLookupName(LookupResult &R, Scope *S, DeclarationName Name, - LookupNameKind NameKind, bool RedeclarationOnly); public: /// Determines whether D is a suitable lookup result according to the /// lookup criteria. @@ -1360,27 +1128,13 @@ public: /// ambiguity and overloaded. NamedDecl *LookupSingleName(Scope *S, DeclarationName Name, LookupNameKind NameKind, - bool RedeclarationOnly = false) { - LookupResult R; - LookupName(R, S, Name, NameKind, RedeclarationOnly); - return R.getAsSingleDecl(Context); - } + RedeclarationKind Redecl + = NotForRedeclaration); bool LookupName(LookupResult &R, Scope *S, - DeclarationName Name, - LookupNameKind NameKind, - bool RedeclarationOnly = false, - bool AllowBuiltinCreation = false, - SourceLocation Loc = SourceLocation()); - bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, - DeclarationName Name, - LookupNameKind NameKind, - bool RedeclarationOnly = false); + bool AllowBuiltinCreation = false); + bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx); bool LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS, - DeclarationName Name, - LookupNameKind NameKind, - bool RedeclarationOnly = false, bool AllowBuiltinCreation = false, - SourceLocation Loc = SourceLocation(), bool EnteringContext = false); ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II); @@ -1398,9 +1152,7 @@ public: AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses); - bool DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name, - SourceLocation NameLoc, - SourceRange LookupRange = SourceRange()); + bool DiagnoseAmbiguousLookup(LookupResult &Result); //@} ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id); @@ -1447,6 +1199,12 @@ public: void ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl, ObjCContainerDecl* IDecl, bool IncompleteImpl = false); + + /// AtomicPropertySetterGetterRules - This routine enforces the rule (via + /// warning) when atomic property has one but not the other user-declared + /// setter or getter. + void AtomicPropertySetterGetterRules(ObjCImplDecl* IMPDecl, + ObjCContainerDecl* IDecl); /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns /// true, or false, accordingly. @@ -1610,7 +1368,8 @@ public: Expr **Args, unsigned NumArgs); void CheckSignCompare(Expr *LHS, Expr *RHS, SourceLocation Loc, - const PartialDiagnostic &PD); + const PartialDiagnostic &PD, + bool Equality = false); virtual ExpressionEvaluationContext PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext); @@ -1746,11 +1505,6 @@ public: const FunctionProtoType *Proto, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc); - void BuildBaseOrMemberInitializers(ASTContext &C, - CXXConstructorDecl *Constructor, - CXXBaseOrMemberInitializer **Initializers, - unsigned NumInitializers - ); void DeconstructCallFunction(Expr *FnExpr, NamedDecl *&Function, @@ -1890,12 +1644,15 @@ public: SourceLocation IdentLoc, IdentifierInfo *Ident); - NamedDecl *BuildUsingDeclaration(SourceLocation UsingLoc, + NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS, + SourceLocation UsingLoc, const CXXScopeSpec &SS, SourceLocation IdentLoc, DeclarationName Name, AttributeList *AttrList, - bool IsTypeName); + bool IsInstantiation, + bool IsTypeName, + SourceLocation TypenameLoc); virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, @@ -1903,7 +1660,8 @@ public: const CXXScopeSpec &SS, UnqualifiedId &Name, AttributeList *AttrList, - bool IsTypeName); + bool IsTypeName, + SourceLocation TypenameLoc); /// AddCXXDirectInitializerToDecl - This action is called immediately after /// ActOnDeclarator, when a C++ direct initializer is present. @@ -1997,6 +1755,12 @@ public: }; CXXConstructorDecl * + TryInitializationByConstructor(QualType ClassType, + Expr **Args, unsigned NumArgs, + SourceLocation Loc, + InitializationKind Kind); + + CXXConstructorDecl * PerformInitializationByConstructor(QualType ClassType, MultiExprArg ArgsPtr, SourceLocation Loc, SourceRange Range, @@ -2088,6 +1852,9 @@ public: void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return, QualType Argument); + bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, + DeclarationName Name, FunctionDecl* &Operator); + /// ActOnCXXDelete - Parsed a C++ 'delete' expression virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, bool ArrayForm, @@ -2276,17 +2043,15 @@ public: SourceLocation RParenLoc, CXXRecordDecl *ClassDecl); - void SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, + bool SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, CXXBaseOrMemberInitializer **Initializers, unsigned NumInitializers, - llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases, - llvm::SmallVectorImpl<FieldDecl *>&Members); + bool IsImplicitConstructor); - /// computeBaseOrMembersToDestroy - Compute information in current - /// destructor decl's AST of bases and non-static data members which will be - /// implicitly destroyed. We are storing the destruction in the order that - /// they should occur (which is the reverse of construction order). - void computeBaseOrMembersToDestroy(CXXDestructorDecl *Destructor); + /// MarkBaseAndMemberDestructorsReferenced - Given a destructor decl, + /// mark all its non-trivial member and base destructor declarations + /// as referenced. + void MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor); void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl); @@ -2320,6 +2085,7 @@ public: void CheckConstructor(CXXConstructorDecl *Constructor); QualType CheckDestructorDeclarator(Declarator &D, FunctionDecl::StorageClass& SC); + void CheckDestructor(CXXDestructorDecl *Destructor); void CheckConversionDeclarator(Declarator &D, QualType &R, FunctionDecl::StorageClass& SC); DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion); @@ -2353,7 +2119,8 @@ public: bool IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths); bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, - SourceLocation Loc, SourceRange Range); + SourceLocation Loc, SourceRange Range, + bool IgnoreAccess = false); bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, unsigned InaccessibleBaseID, unsigned AmbigiousBaseConvID, @@ -2451,7 +2218,7 @@ public: unsigned Position); virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam, SourceLocation EqualLoc, - ExprArg Default); + const ParsedTemplateArgument &Default); virtual TemplateParamsTy * ActOnTemplateParameterList(unsigned Depth, @@ -2477,8 +2244,7 @@ public: AccessSpecifier AS); void translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, - SourceLocation *TemplateArgLocsIn, - llvm::SmallVector<TemplateArgumentLoc, 16> &TempArgs); + llvm::SmallVectorImpl<TemplateArgumentLoc> &TempArgs); QualType CheckTemplateIdType(TemplateName Template, SourceLocation TemplateLoc, @@ -2491,7 +2257,6 @@ public: ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc); virtual TypeResult ActOnTagTemplateIdType(TypeResult Type, @@ -2513,7 +2278,6 @@ public: SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc); virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, @@ -2534,7 +2298,6 @@ public: SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc, AttributeList *Attr, MultiTemplateParamsArg TemplateParameterLists); @@ -2575,7 +2338,6 @@ public: SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc, AttributeList *Attr); @@ -2595,6 +2357,13 @@ public: SourceLocation TemplateLoc, Declarator &D); + bool CheckTemplateArgument(NamedDecl *Param, + const TemplateArgumentLoc &Arg, + TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + TemplateArgumentListBuilder &Converted); + bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, @@ -2612,17 +2381,54 @@ public: DeclaratorInfo *Arg); bool CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, NamedDecl *&Entity); - bool CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member); + bool CheckTemplateArgumentPointerToMember(Expr *Arg, + TemplateArgument &Converted); bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType InstantiatedParamType, Expr *&Arg, TemplateArgument &Converted); - bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, DeclRefExpr *Arg); + bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, + const TemplateArgumentLoc &Arg); + + /// \brief Enumeration describing how template parameter lists are compared + /// for equality. + enum TemplateParameterListEqualKind { + /// \brief We are matching the template parameter lists of two templates + /// that might be redeclarations. + /// + /// \code + /// template<typename T> struct X; + /// template<typename T> struct X; + /// \endcode + TPL_TemplateMatch, + + /// \brief We are matching the template parameter lists of two template + /// template parameters as part of matching the template parameter lists + /// of two templates that might be redeclarations. + /// + /// \code + /// template<template<int I> class TT> struct X; + /// template<template<int Value> class Other> struct X; + /// \endcode + TPL_TemplateTemplateParmMatch, + + /// \brief We are matching the template parameter lists of a template + /// template argument against the template parameter lists of a template + /// template parameter. + /// + /// \code + /// template<template<int Value> class Metafun> struct X; + /// template<int Value> struct integer_c; + /// X<integer_c> xic; + /// \endcode + TPL_TemplateTemplateArgumentMatch + }; + bool TemplateParameterListsAreEqual(TemplateParameterList *New, TemplateParameterList *Old, bool Complain, - bool IsTemplateTemplateParm = false, + TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc - = SourceLocation()); + = SourceLocation()); bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams); @@ -2659,6 +2465,11 @@ public: std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args); + + std::string + getTemplateArgumentBindingsText(const TemplateParameterList *Params, + const TemplateArgument *Args, + unsigned NumArgs); /// \brief Describes the result of template argument deduction. /// @@ -2849,7 +2660,8 @@ public: // C++ Template Instantiation // - MultiLevelTemplateArgumentList getTemplateInstantiationArgs(NamedDecl *D); + MultiLevelTemplateArgumentList getTemplateInstantiationArgs(NamedDecl *D, + const TemplateArgumentList *Innermost = 0); /// \brief A template instantiation that is currently in progress. struct ActiveTemplateInstantiation { @@ -2880,17 +2692,30 @@ public: /// partial specialization or a function template. The /// Entity is either a ClassTemplatePartialSpecializationDecl or /// a FunctionTemplateDecl. - DeducedTemplateArgumentSubstitution + DeducedTemplateArgumentSubstitution, + + /// We are substituting prior template arguments into a new + /// template parameter. The template parameter itself is either a + /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl. + PriorTemplateArgumentSubstitution, + + /// We are checking the validity of a default template argument that + /// has been used when naming a template-id. + DefaultTemplateArgumentChecking } Kind; /// \brief The point of instantiation within the source code. SourceLocation PointOfInstantiation; + /// \brief The template in which we are performing the instantiation, + /// for substitutions of prior template arguments. + TemplateDecl *Template; + /// \brief The entity that is being instantiated. uintptr_t Entity; - // \brief If this the instantiation of a default template - // argument, the list of template arguments. + /// \brief The list of template arguments we are substituting, if they + /// are not part of the entity. const TemplateArgument *TemplateArgs; /// \brief The number of template arguments in TemplateArgs. @@ -2901,9 +2726,14 @@ public: /// template instantiation. SourceRange InstantiationRange; - ActiveTemplateInstantiation() : Kind(TemplateInstantiation), Entity(0), - TemplateArgs(0), NumTemplateArgs(0) {} + ActiveTemplateInstantiation() + : Kind(TemplateInstantiation), Template(0), Entity(0), TemplateArgs(0), + NumTemplateArgs(0) {} + /// \brief Determines whether this template is an actual instantiation + /// that should be counted toward the maximum instantiation depth. + bool isInstantiationRecord() const; + friend bool operator==(const ActiveTemplateInstantiation &X, const ActiveTemplateInstantiation &Y) { if (X.Kind != Y.Kind) @@ -2916,6 +2746,13 @@ public: case TemplateInstantiation: return true; + case PriorTemplateArgumentSubstitution: + case DefaultTemplateArgumentChecking: + if (X.Template != Y.Template) + return false; + + // Fall through + case DefaultTemplateArgumentInstantiation: case ExplicitTemplateArgumentSubstitution: case DeducedTemplateArgumentSubstitution: @@ -2942,6 +2779,11 @@ public: llvm::SmallVector<ActiveTemplateInstantiation, 16> ActiveTemplateInstantiations; + /// \brief The number of ActiveTemplateInstantiation entries in + /// \c ActiveTemplateInstantiations that are not actual instantiations and, + /// therefore, should not be counted as part of the instantiation depth. + unsigned NonInstantiationEntries; + /// \brief The last template from which a template instantiation /// error or warning was produced. /// @@ -3001,6 +2843,32 @@ public: unsigned NumTemplateArgs, SourceRange InstantiationRange = SourceRange()); + /// \brief Note that we are substituting prior template arguments into a + /// non-type or template template parameter. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + NonTypeTemplateParmDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange); + + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + TemplateTemplateParmDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange); + + /// \brief Note that we are checking the default template argument + /// against the template parameter for a given template-id. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + NamedDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange); + + /// \brief Note that we have finished instantiating this template. void Clear(); @@ -3273,8 +3141,9 @@ public: SourceLocation CatLoc); virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation Loc, - IdentifierInfo **IdentList, - unsigned NumElts); + IdentifierInfo **IdentList, + SourceLocation *IdentLocs, + unsigned NumElts); virtual DeclPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, const IdentifierLocPair *IdentList, @@ -3484,6 +3353,12 @@ public: /// CompatiblePointerDiscardsQualifiers - The assignment discards /// c/v/r qualifiers, which we accept as an extension. CompatiblePointerDiscardsQualifiers, + + /// IncompatibleNestedPointerQualifiers - The assignment is between two + /// nested pointer types, and the qualifiers other than the first two + /// levels differ e.g. char ** -> const char **, but we accept them as an + /// extension. + IncompatibleNestedPointerQualifiers, /// IncompatibleVectors - The assignment is between two vector types that /// have the same size, which we accept as an extension. @@ -3555,10 +3430,11 @@ public: ImplicitConversionSequence& ICS); bool PerformImplicitConversion(Expr *&From, QualType ToType, const ImplicitConversionSequence& ICS, - const char *Flavor); + const char *Flavor, + bool IgnoreBaseAccess = false); bool PerformImplicitConversion(Expr *&From, QualType ToType, const StandardConversionSequence& SCS, - const char *Flavor); + const char *Flavor, bool IgnoreBaseAccess); bool BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind, const ImplicitConversionSequence& ICS, @@ -3660,7 +3536,8 @@ public: bool SuppressUserConversions, bool AllowExplicit, bool ForceRValue, - ImplicitConversionSequence *ICS = 0); + ImplicitConversionSequence *ICS = 0, + bool IgnoreBaseAccess = false); /// CheckCastTypes - Check type constraints for casting between types under /// C semantics, or forward to CXXCheckCStyleCast in C++. @@ -3745,7 +3622,6 @@ public: /// \name Code completion //@{ - void setCodeCompleteConsumer(CodeCompleteConsumer *CCC); virtual void CodeCompleteOrdinaryName(Scope *S); virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base, SourceLocation OpLoc, @@ -3763,7 +3639,13 @@ public: virtual void CodeCompleteOperatorName(Scope *S); virtual void CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS); - //@} + virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, + SourceLocation FNameLoc); + virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver); + virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, + unsigned NumProtocols); + virtual void CodeCompleteObjCProtocolDecl(Scope *S); + //@} //===--------------------------------------------------------------------===// // Extra semantic analysis beyond the C type system @@ -3808,7 +3690,6 @@ private: void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex); }; - //===--------------------------------------------------------------------===// // Typed version of Parser::ExprArg (smart pointer for wrapping Expr pointers). template <typename T> diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index 0a5335a..5769716 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "Lookup.h" #include "clang/AST/Expr.h" using namespace clang; @@ -179,10 +180,8 @@ void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers, for (unsigned i = 0; i < NumIdentifiers; ++i) { const Token &Tok = Identifiers[i]; IdentifierInfo *Name = Tok.getIdentifierInfo(); - LookupResult Lookup; - LookupParsedName(Lookup, curScope, NULL, Name,LookupOrdinaryName, - false, true, Tok.getLocation()); - // FIXME: Handle Lookup.isAmbiguous? + LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName); + LookupParsedName(Lookup, curScope, NULL, true); NamedDecl *ND = Lookup.getAsSingleDecl(Context); diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 76faddaa..e5ad338 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -70,28 +70,31 @@ static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, - unsigned &msg); + unsigned &msg, + CastExpr::CastKind &Kind); static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType, bool CStyle, const SourceRange &OpRange, - unsigned &msg); -static TryCastResult TryStaticDowncast(Sema &Self, QualType SrcType, - QualType DestType, bool CStyle, + unsigned &msg, + CastExpr::CastKind &Kind); +static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, + CanQualType DestType, bool CStyle, const SourceRange &OpRange, QualType OrigSrcType, - QualType OrigDestType, unsigned &msg); + QualType OrigDestType, unsigned &msg, + CastExpr::CastKind &Kind); static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType,bool CStyle, const SourceRange &OpRange, unsigned &msg, CastExpr::CastKind &Kind); -static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, +static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, CastExpr::CastKind &Kind, CXXMethodDecl *&ConversionDecl); -static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr, +static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, @@ -187,7 +190,8 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { assert((DestType->isPointerType() || DestType->isMemberPointerType()) && "Destination type is not pointer or pointer to member."); - QualType UnwrappedSrcType = SrcType, UnwrappedDestType = DestType; + QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType), + UnwrappedDestType = Self.Context.getCanonicalType(DestType); llvm::SmallVector<Qualifiers, 8> cv1, cv2; // Find the qualifications. @@ -385,14 +389,15 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (DestType->isVoidType()) { + Kind = CastExpr::CK_ToVoid; return; } - if (!DestType->isLValueReferenceType()) + if (!DestType->isLValueReferenceType() && !DestType->isRecordType()) Self.DefaultFunctionArrayConversion(SrcExpr); unsigned msg = diag::err_bad_cxx_cast_generic; - if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false,OpRange, msg, + if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg, Kind, ConversionDecl) != TC_Success && msg != 0) Self.Diag(OpRange.getBegin(), msg) << CT_Static @@ -402,7 +407,7 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, /// TryStaticCast - Check if a static cast can be performed, and do so if /// possible. If @p CStyle, ignore access restrictions on hierarchy casting /// and casting away constness. -static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr, +static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, CastExpr::CastKind &Kind, @@ -427,15 +432,18 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr, // C++ 5.2.9p5, reference downcast. // See the function for details. // DR 427 specifies that this is to be applied before paragraph 2. - tcr = TryStaticReferenceDowncast(Self, SrcExpr, DestType, CStyle,OpRange,msg); + tcr = TryStaticReferenceDowncast(Self, SrcExpr, DestType, CStyle, OpRange, + msg, Kind); if (tcr != TC_NotApplicable) return tcr; // N2844 5.2.9p3: An lvalue of type "cv1 T1" can be cast to type "rvalue // reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1". tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, msg); - if (tcr != TC_NotApplicable) + if (tcr != TC_NotApplicable) { + Kind = CastExpr::CK_NoOp; return tcr; + } // C++ 5.2.9p2: An expression e can be explicitly converted to a type T // [...] if the declaration "T t(e);" is well-formed, [...]. @@ -467,13 +475,16 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr, if (DestType->isEnumeralType()) { if (SrcType->isComplexType() || SrcType->isVectorType()) { // Fall through - these cannot be converted. - } else if (SrcType->isArithmeticType() || SrcType->isEnumeralType()) + } else if (SrcType->isArithmeticType() || SrcType->isEnumeralType()) { + Kind = CastExpr::CK_IntegralCast; return TC_Success; + } } // Reverse pointer upcast. C++ 4.10p3 specifies pointer upcast. // C++ 5.2.9p8 additionally disallows a cast path through virtual inheritance. - tcr = TryStaticPointerDowncast(Self, SrcType, DestType, CStyle, OpRange, msg); + tcr = TryStaticPointerDowncast(Self, SrcType, DestType, CStyle, OpRange, msg, + Kind); if (tcr != TC_NotApplicable) return tcr; @@ -500,6 +511,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr, msg = diag::err_bad_cxx_cast_const_away; return TC_Failed; } + Kind = CastExpr::CK_BitCast; return TC_Success; } } @@ -544,7 +556,7 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType, TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, - unsigned &msg) { + unsigned &msg, CastExpr::CastKind &Kind) { // C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be // cast to type "reference to cv2 D", where D is a class derived from B, // if a valid standard conversion from "pointer to D" to "pointer to B" @@ -567,15 +579,17 @@ TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, QualType DestPointee = DestReference->getPointeeType(); - return TryStaticDowncast(Self, SrcExpr->getType(), DestPointee, CStyle, - OpRange, SrcExpr->getType(), DestType, msg); + return TryStaticDowncast(Self, + Self.Context.getCanonicalType(SrcExpr->getType()), + Self.Context.getCanonicalType(DestPointee), CStyle, + OpRange, SrcExpr->getType(), DestType, msg, Kind); } /// Tests whether a conversion according to C++ 5.2.9p8 is valid. TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType, bool CStyle, const SourceRange &OpRange, - unsigned &msg) { + unsigned &msg, CastExpr::CastKind &Kind) { // C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class // type, can be converted to an rvalue of type "pointer to cv2 D", where D // is a class derived from B, if a valid standard conversion from "pointer @@ -595,25 +609,27 @@ TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType, return TC_NotApplicable; } - return TryStaticDowncast(Self, SrcPointer->getPointeeType(), - DestPointer->getPointeeType(), CStyle, - OpRange, SrcType, DestType, msg); + return TryStaticDowncast(Self, + Self.Context.getCanonicalType(SrcPointer->getPointeeType()), + Self.Context.getCanonicalType(DestPointer->getPointeeType()), + CStyle, OpRange, SrcType, DestType, msg, Kind); } /// TryStaticDowncast - Common functionality of TryStaticReferenceDowncast and /// TryStaticPointerDowncast. Tests whether a static downcast from SrcType to -/// DestType, both of which must be canonical, is possible and allowed. +/// DestType is possible and allowed. TryCastResult -TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType, +TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, bool CStyle, const SourceRange &OpRange, QualType OrigSrcType, - QualType OrigDestType, unsigned &msg) { + QualType OrigDestType, unsigned &msg, + CastExpr::CastKind &Kind) { // We can only work with complete types. But don't complain if it doesn't work if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, PDiag(0)) || Self.RequireCompleteType(OpRange.getBegin(), DestType, PDiag(0))) return TC_NotApplicable; // Downcast can only happen in class hierarchies, so we need classes. - if (!DestType->isRecordType() || !SrcType->isRecordType()) { + if (!DestType->getAs<RecordType>() || !SrcType->getAs<RecordType>()) { return TC_NotApplicable; } @@ -669,12 +685,13 @@ TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType, EE = PI->rend(); EI != EE; ++EI) PathDisplayStr += EI->Base->getType().getAsString() + " -> "; - PathDisplayStr += DestType.getAsString(); + PathDisplayStr += QualType(DestType).getAsString(); } } Self.Diag(OpRange.getBegin(), diag::err_ambiguous_base_to_derived_cast) - << SrcType.getUnqualifiedType() << DestType.getUnqualifiedType() + << QualType(SrcType).getUnqualifiedType() + << QualType(DestType).getUnqualifiedType() << PathDisplayStr << OpRange; msg = 0; return TC_Failed; @@ -695,6 +712,7 @@ TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType, return TC_Failed; } + Kind = CastExpr::CK_BaseToDerived; return TC_Success; } @@ -719,10 +737,8 @@ TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType, } // T == T, modulo cv - if (Self.Context.getCanonicalType( - SrcMemPtr->getPointeeType().getUnqualifiedType()) != - Self.Context.getCanonicalType(DestMemPtr->getPointeeType(). - getUnqualifiedType())) + if (!Self.Context.hasSameUnqualifiedType(SrcMemPtr->getPointeeType(), + DestMemPtr->getPointeeType())) return TC_NotApplicable; // B base of D @@ -772,7 +788,7 @@ TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType, /// An expression e can be explicitly converted to a type T using a /// @c static_cast if the declaration "T t(e);" is well-formed [...]. TryCastResult -TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType, +TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, CastExpr::CastKind &Kind, CXXMethodDecl *&ConversionDecl) { @@ -785,27 +801,49 @@ TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType, } if (DestType->isReferenceType()) { + // All reference bindings insert implicit casts above that do the actual + // casting. + Kind = CastExpr::CK_NoOp; + // At this point of CheckStaticCast, if the destination is a reference, // this has to work. There is no other way that works. // On the other hand, if we're checking a C-style cast, we've still got - // the reinterpret_cast way. In that case, we pass an ICS so we don't - // get error messages. - ImplicitConversionSequence ICS; - bool failed = Self.CheckReferenceInit(SrcExpr, DestType, - OpRange.getBegin(), - /*SuppressUserConversions=*/false, - /*AllowExplicit=*/false, - /*ForceRValue=*/false, - CStyle ? &ICS : 0); - if (!failed) + // the reinterpret_cast way. So in C-style mode, we first try the call + // with an ICS to suppress errors. + if (CStyle) { + ImplicitConversionSequence ICS; + if(Self.CheckReferenceInit(SrcExpr, DestType, OpRange.getBegin(), + /*SuppressUserConversions=*/false, + /*AllowExplicit=*/false, /*ForceRValue=*/false, + &ICS)) + return TC_NotApplicable; + } + // Now we're committed either way. + if(!Self.CheckReferenceInit(SrcExpr, DestType, OpRange.getBegin(), + /*SuppressUserConversions=*/false, + /*AllowExplicit=*/false, + /*ForceRValue=*/false, 0, + /*IgnoreBaseAccess=*/CStyle)) return TC_Success; - if (CStyle) - return TC_NotApplicable; - // If we didn't pass the ICS, we already got an error message. + + // We already got an error message. msg = 0; return TC_Failed; } + if (DestType->isRecordType()) { + if (CXXConstructorDecl *Constructor + = Self.TryInitializationByConstructor(DestType, &SrcExpr, 1, + OpRange.getBegin(), + Sema::IK_Direct)) { + ConversionDecl = Constructor; + Kind = CastExpr::CK_ConstructorConversion; + return TC_Success; + } + + return TC_NotApplicable; + } + // FIXME: To get a proper error from invalid conversions here, we need to // reimplement more of this. // FIXME: This does not actually perform the conversion, and thus does not @@ -821,18 +859,12 @@ TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType, if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion) return TC_NotApplicable; - if (ICS.ConversionKind == ImplicitConversionSequence::UserDefinedConversion) { - ConversionDecl = cast<CXXMethodDecl>(ICS.UserDefined.ConversionFunction); - if (isa<CXXConstructorDecl>(ConversionDecl)) - Kind = CastExpr::CK_ConstructorConversion; - else if (isa<CXXConversionDecl>(ConversionDecl)) - Kind = CastExpr::CK_UserDefinedConversion; - } else if (ICS.ConversionKind == - ImplicitConversionSequence::StandardConversion) { - // FIXME: Set the cast kind depending on which types of conversions we have. - } - - return TC_Success; + // The conversion is possible, so commit to it. + Kind = CastExpr::CK_NoOp; + msg = 0; + return Self.PerformImplicitConversion(SrcExpr, DestType, ICS, "casting", + /*IgnoreBaseAccess*/CStyle) ? + TC_Failed : TC_Success; } /// TryConstCast - See if a const_cast from source to destination is allowed, @@ -1104,7 +1136,7 @@ bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr, if (CastTy->isDependentType() || CastExpr->isTypeDependent()) return false; - if (!CastTy->isLValueReferenceType()) + if (!CastTy->isLValueReferenceType() && !CastTy->isRecordType()) DefaultFunctionArrayConversion(CastExpr); // C++ [expr.cast]p5: The conversions performed by diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index ce3fb5f..34a5b78 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "Lookup.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" @@ -307,8 +308,9 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) { if (NNS->getKind() != NestedNameSpecifier::Identifier) return 0; - LookupResult Found; - LookupName(Found, S, NNS->getAsIdentifier(), LookupNestedNameSpecifierName); + LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(), + LookupNestedNameSpecifierName); + LookupName(Found, S); assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet"); NamedDecl *Result = Found.getAsSingleDecl(Context); @@ -336,6 +338,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecifier *Prefix = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName); + // Determine where to perform name lookup DeclContext *LookupCtx = 0; bool isDependent = false; @@ -350,9 +354,10 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, // so long into the context associated with the prior nested-name-specifier. LookupCtx = computeDeclContext(SS, EnteringContext); isDependent = isDependentScopeSpecifier(SS); + Found.setContextRange(SS.getRange()); } - LookupResult Found; + bool ObjectTypeSearchedInScope = false; if (LookupCtx) { // Perform "qualified" name lookup into the declaration context we @@ -364,10 +369,9 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS)) return 0; - LookupQualifiedName(Found, LookupCtx, &II, LookupNestedNameSpecifierName, - false); + LookupQualifiedName(Found, LookupCtx); - if (!ObjectType.isNull() && Found.getKind() == LookupResult::NotFound) { + if (!ObjectType.isNull() && Found.empty()) { // C++ [basic.lookup.classref]p4: // If the id-expression in a class member access is a qualified-id of // the form @@ -389,7 +393,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, // reconstruct the result from when name lookup was performed at template // definition time. if (S) - LookupName(Found, S, &II, LookupNestedNameSpecifierName); + LookupName(Found, S); else if (ScopeLookupResult) Found.addDecl(ScopeLookupResult); @@ -406,7 +410,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, return NestedNameSpecifier::Create(Context, Prefix, &II); } else { // Perform unqualified name lookup in the current scope. - LookupName(Found, S, &II, LookupNestedNameSpecifierName); + LookupName(Found, S); } // FIXME: Deal with ambiguities cleanly. @@ -423,9 +427,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, // scope, reconstruct the result from the template instantiation itself. NamedDecl *OuterDecl; if (S) { - LookupResult FoundOuter; - LookupName(FoundOuter, S, &II, LookupNestedNameSpecifierName); - // FIXME: Handle ambiguities! + LookupResult FoundOuter(*this, &II, IdLoc, LookupNestedNameSpecifierName); + LookupName(FoundOuter, S); OuterDecl = FoundOuter.getAsSingleDecl(Context); } else OuterDecl = ScopeLookupResult; @@ -467,8 +470,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, // ordinary name lookup, which can help us produce better error // messages. if (!SD) { - Found.clear(); - LookupName(Found, S, &II, LookupOrdinaryName); + Found.clear(LookupOrdinaryName); + LookupName(Found, S); SD = Found.getAsSingleDecl(Context); } diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 38b6ebe..9060fe6 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -91,6 +91,12 @@ bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) { if (Format->getType() == "printf0") { // printf0 allows null "format" string; if so don't check format/args unsigned format_idx = Format->getFormatIdx() - 1; + // Does the index refer to the implicit object argument? + if (isa<CXXMemberCallExpr>(TheCall)) { + if (format_idx == 0) + return false; + --format_idx; + } if (format_idx < TheCall->getNumArgs()) { Expr *Format = TheCall->getArg(format_idx)->IgnoreParenCasts(); if (!Format->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) @@ -204,7 +210,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { if (!HasVAListArg) { if (const FunctionProtoType *Proto = FDecl->getType()->getAs<FunctionProtoType>()) - HasVAListArg = !Proto->isVariadic(); + HasVAListArg = !Proto->isVariadic(); } CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1, HasVAListArg ? 0 : Format->getFirstArg() - 1); @@ -628,8 +634,7 @@ Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { return ExprError(); } - if (Context.getCanonicalType(FAType).getUnqualifiedType() != - Context.getCanonicalType(SAType).getUnqualifiedType()) { + if (!Context.hasSameUnqualifiedType(FAType, SAType)) { Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) << SourceRange(TheCall->getArg(0)->getLocStart(), TheCall->getArg(1)->getLocEnd()); @@ -971,6 +976,18 @@ Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg) { const Expr *Fn = TheCall->getCallee(); + // The way the format attribute works in GCC, the implicit this argument + // of member functions is counted. However, it doesn't appear in our own + // lists, so decrement format_idx in that case. + if (isa<CXXMemberCallExpr>(TheCall)) { + // Catch a format attribute mistakenly referring to the object argument. + if (format_idx == 0) + return; + --format_idx; + if(firstDataArg != 0) + --firstDataArg; + } + // CHECK: printf-like function is called with no format string. if (format_idx >= TheCall->getNumArgs()) { Diag(TheCall->getRParenLoc(), diag::warn_printf_missing_format_string) diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index e9df17d..9cecdad 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -13,6 +13,7 @@ #include "Sema.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/SmallPtrSet.h" @@ -23,13 +24,6 @@ using namespace clang; -/// \brief Set the code-completion consumer for semantic analysis. -void Sema::setCodeCompleteConsumer(CodeCompleteConsumer *CCC) { - assert(((CodeCompleter != 0) != (CCC != 0)) && - "Already set or cleared a code-completion consumer?"); - CodeCompleter = CCC; -} - namespace { /// \brief A container of code-completion results. class ResultBuilder { @@ -101,6 +95,9 @@ namespace { /// \brief Exit from the current scope. void ExitScope(); + /// \brief Ignore this declaration, if it is seen again. + void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); } + /// \name Name lookup predicates /// /// These predicates can be passed to the name lookup functions to filter the @@ -187,8 +184,7 @@ getRequiredQualification(ASTContext &Context, Context.getTypeDeclType(TD).getTypePtr()); else assert(Parent->isTranslationUnit()); - } - + } return Result; } @@ -206,7 +202,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { return; // Look through using declarations. - if (UsingDecl *Using = dyn_cast<UsingDecl>(R.Declaration)) + if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) MaybeAddResult(Result(Using->getTargetDecl(), R.Rank, R.Qualifier), CurContext); @@ -474,17 +470,24 @@ static unsigned CollectMemberLookupResults(DeclContext *Ctx, for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx; CurCtx = CurCtx->getNextContext()) { for (DeclContext::decl_iterator D = CurCtx->decls_begin(), - DEnd = CurCtx->decls_end(); + DEnd = CurCtx->decls_end(); D != DEnd; ++D) { if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) Results.MaybeAddResult(Result(ND, Rank, 0, InBaseClass), CurContext); + + // Visit transparent contexts inside this context. + if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) { + if (InnerCtx->isTransparentContext()) + CollectMemberLookupResults(InnerCtx, Rank, CurContext, Visited, + Results, InBaseClass); + } } } // Traverse the contexts of inherited classes. if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) { for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(), - BEnd = Record->bases_end(); + BEnd = Record->bases_end(); B != BEnd; ++B) { QualType BaseType = B->getType(); @@ -674,6 +677,8 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, unsigned Rank, static void AddFunctionParameterChunks(ASTContext &Context, FunctionDecl *Function, CodeCompletionString *Result) { + typedef CodeCompletionString::Chunk Chunk; + CodeCompletionString *CCStr = Result; for (unsigned P = 0, N = Function->getNumParams(); P != N; ++P) { @@ -688,7 +693,7 @@ static void AddFunctionParameterChunks(ASTContext &Context, } if (P != 0) - CCStr->AddTextChunk(", "); + CCStr->AddChunk(Chunk(CodeCompletionString::CK_Comma)); // Format the placeholder string. std::string PlaceholderStr; @@ -713,6 +718,8 @@ static void AddTemplateParameterChunks(ASTContext &Context, TemplateDecl *Template, CodeCompletionString *Result, unsigned MaxParameters = 0) { + typedef CodeCompletionString::Chunk Chunk; + CodeCompletionString *CCStr = Result; bool FirstParameter = true; @@ -768,7 +775,7 @@ static void AddTemplateParameterChunks(ASTContext &Context, if (FirstParameter) FirstParameter = false; else - CCStr->AddTextChunk(", "); + CCStr->AddChunk(Chunk(CodeCompletionString::CK_Comma)); // Add the placeholder string. CCStr->AddPlaceholderChunk(PlaceholderStr.c_str()); @@ -803,6 +810,8 @@ void AddQualifierToCompletionString(CodeCompletionString *Result, /// result is all that is needed. CodeCompletionString * CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { + typedef CodeCompletionString::Chunk Chunk; + if (Kind == RK_Keyword) return 0; @@ -813,12 +822,12 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { // Format a function-like macro with placeholders for the arguments. CodeCompletionString *Result = new CodeCompletionString; - Result->AddTextChunk(Macro->getName().str().c_str()); - Result->AddTextChunk("("); + 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) { if (A != MI->arg_begin()) - Result->AddTextChunk(", "); + Result->AddChunk(Chunk(CodeCompletionString::CK_Comma)); if (!MI->isVariadic() || A != AEnd - 1) { // Non-variadic argument. @@ -837,21 +846,28 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { Result->AddPlaceholderChunk(Arg.c_str()); } } - Result->AddTextChunk(")"); + Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen)); return Result; } assert(Kind == RK_Declaration && "Missed a macro kind?"); NamedDecl *ND = Declaration; + if (StartsNestedNameSpecifier) { + CodeCompletionString *Result = new CodeCompletionString; + Result->AddTypedTextChunk(ND->getNameAsString().c_str()); + Result->AddTextChunk("::"); + return Result; + } + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { CodeCompletionString *Result = new CodeCompletionString; AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, S.Context); - Result->AddTextChunk(Function->getNameAsString().c_str()); - Result->AddTextChunk("("); + Result->AddTypedTextChunk(Function->getNameAsString().c_str()); + Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); AddFunctionParameterChunks(S.Context, Function, Result); - Result->AddTextChunk(")"); + Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen)); return Result; } @@ -860,7 +876,7 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, S.Context); FunctionDecl *Function = FunTmpl->getTemplatedDecl(); - Result->AddTextChunk(Function->getNameAsString().c_str()); + Result->AddTypedTextChunk(Function->getNameAsString().c_str()); // Figure out which template parameters are deduced (or have default // arguments). @@ -884,7 +900,7 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { else { assert(isa<TemplateTemplateParmDecl>(Param)); HasDefaultArg - = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument(); + = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument(); } if (!HasDefaultArg) @@ -896,16 +912,16 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { // Some of the function template arguments cannot be deduced from a // function call, so we introduce an explicit template argument list // containing all of the arguments up to the first deducible argument. - Result->AddTextChunk("<"); + Result->AddChunk(Chunk(CodeCompletionString::CK_LeftAngle)); AddTemplateParameterChunks(S.Context, FunTmpl, Result, LastDeducibleArgument); - Result->AddTextChunk(">"); + Result->AddChunk(Chunk(CodeCompletionString::CK_RightAngle)); } // Add the function parameters - Result->AddTextChunk("("); + Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); AddFunctionParameterChunks(S.Context, Function, Result); - Result->AddTextChunk(")"); + Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen)); return Result; } @@ -913,20 +929,51 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { CodeCompletionString *Result = new CodeCompletionString; AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, S.Context); - Result->AddTextChunk(Template->getNameAsString().c_str()); - Result->AddTextChunk("<"); + Result->AddTypedTextChunk(Template->getNameAsString().c_str()); + Result->AddChunk(Chunk(CodeCompletionString::CK_LeftAngle)); AddTemplateParameterChunks(S.Context, Template, Result); - Result->AddTextChunk(">"); + Result->AddChunk(Chunk(CodeCompletionString::CK_RightAngle)); return Result; } - if (Qualifier || StartsNestedNameSpecifier) { + if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) { + CodeCompletionString *Result = new CodeCompletionString; + Selector Sel = Method->getSelector(); + if (Sel.isUnarySelector()) { + Result->AddTypedTextChunk(Sel.getIdentifierInfoForSlot(0)->getName()); + return Result; + } + + Result->AddTypedTextChunk( + Sel.getIdentifierInfoForSlot(0)->getName().str() + std::string(":")); + unsigned Idx = 0; + for (ObjCMethodDecl::param_iterator P = Method->param_begin(), + PEnd = Method->param_end(); + P != PEnd; (void)++P, ++Idx) { + if (Idx > 0) { + std::string Keyword = " "; + if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx)) + Keyword += II->getName().str(); + Keyword += ":"; + Result->AddTextChunk(Keyword); + } + + std::string Arg; + (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy); + Arg = "(" + Arg + ")"; + if (IdentifierInfo *II = (*P)->getIdentifier()) + Arg += II->getName().str(); + Result->AddPlaceholderChunk(Arg); + } + + return Result; + } + + if (Qualifier) { CodeCompletionString *Result = new CodeCompletionString; AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, S.Context); - Result->AddTextChunk(ND->getNameAsString().c_str()); - if (StartsNestedNameSpecifier) - Result->AddTextChunk("::"); + Result->AddTypedTextChunk(ND->getNameAsString().c_str()); return Result; } @@ -937,6 +984,8 @@ CodeCompletionString * CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( unsigned CurrentArg, Sema &S) const { + typedef CodeCompletionString::Chunk Chunk; + CodeCompletionString *Result = new CodeCompletionString; FunctionDecl *FDecl = getFunction(); const FunctionProtoType *Proto @@ -947,9 +996,9 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( const FunctionType *FT = getFunctionType(); Result->AddTextChunk( FT->getResultType().getAsString(S.Context.PrintingPolicy).c_str()); - Result->AddTextChunk("("); - Result->AddPlaceholderChunk("..."); - Result->AddTextChunk("("); + Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); + Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "...")); + Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen)); return Result; } @@ -959,11 +1008,11 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( Result->AddTextChunk( Proto->getResultType().getAsString(S.Context.PrintingPolicy).c_str()); - Result->AddTextChunk("("); + Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs(); for (unsigned I = 0; I != NumParams; ++I) { if (I) - Result->AddTextChunk(", "); + Result->AddChunk(Chunk(CodeCompletionString::CK_Comma)); std::string ArgString; QualType ArgType; @@ -978,19 +1027,20 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( ArgType.getAsStringInternal(ArgString, S.Context.PrintingPolicy); if (I == CurrentArg) - Result->AddPlaceholderChunk(ArgString.c_str()); + Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, + ArgString.c_str())); else Result->AddTextChunk(ArgString.c_str()); } if (Proto && Proto->isVariadic()) { - Result->AddTextChunk(", "); + Result->AddChunk(Chunk(CodeCompletionString::CK_Comma)); if (CurrentArg < NumParams) Result->AddTextChunk("..."); else - Result->AddPlaceholderChunk("..."); + Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "...")); } - Result->AddTextChunk(")"); + Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen)); return Result; } @@ -1000,7 +1050,9 @@ namespace { typedef CodeCompleteConsumer::Result Result; bool isEarlierDeclarationName(DeclarationName X, DeclarationName Y) const { - if (X.getNameKind() != Y.getNameKind()) + if (!X.getObjCSelector().isNull() && !Y.getObjCSelector().isNull()) { + // Consider all selector kinds to be equivalent. + } else if (X.getNameKind() != Y.getNameKind()) return X.getNameKind() < Y.getNameKind(); return llvm::LowercaseString(X.getAsString()) @@ -1049,32 +1101,77 @@ namespace { }; } -// Add all of the known macros as code-completion results. static void AddMacroResults(Preprocessor &PP, unsigned Rank, ResultBuilder &Results) { Results.EnterNewScope(); - for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end(); + for (Preprocessor::macro_iterator M = PP.macro_begin(), + MEnd = PP.macro_end(); M != MEnd; ++M) Results.MaybeAddResult(CodeCompleteConsumer::Result(M->first, Rank)); Results.ExitScope(); } -static void HandleCodeCompleteResults(CodeCompleteConsumer *CodeCompleter, - CodeCompleteConsumer::Result *Results, - unsigned NumResults) { +static void HandleCodeCompleteResults(Sema *S, + CodeCompleteConsumer *CodeCompleter, + CodeCompleteConsumer::Result *Results, + unsigned NumResults) { // Sort the results by rank/kind/etc. std::stable_sort(Results, Results + NumResults, SortCodeCompleteResult()); if (CodeCompleter) - CodeCompleter->ProcessCodeCompleteResults(Results, NumResults); + CodeCompleter->ProcessCodeCompleteResults(*S, Results, NumResults); } void Sema::CodeCompleteOrdinaryName(Scope *S) { ResultBuilder Results(*this, &ResultBuilder::IsOrdinaryName); unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext, Results); - AddMacroResults(PP, NextRank, Results); - HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, NextRank, Results); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + +static void AddObjCProperties(ObjCContainerDecl *Container, + DeclContext *CurContext, + ResultBuilder &Results) { + typedef CodeCompleteConsumer::Result Result; + + // Add properties in this container. + for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(), + PEnd = Container->prop_end(); + P != PEnd; + ++P) + Results.MaybeAddResult(Result(*P, 0), CurContext); + + // Add properties in referenced protocols. + if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { + for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), + PEnd = Protocol->protocol_end(); + P != PEnd; ++P) + AddObjCProperties(*P, CurContext, Results); + } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){ + // Look through categories. + for (ObjCCategoryDecl *Category = IFace->getCategoryList(); + Category; Category = Category->getNextClassCategory()) + AddObjCProperties(Category, CurContext, Results); + + // Look through protocols. + for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(), + E = IFace->protocol_end(); + I != E; ++I) + AddObjCProperties(*I, CurContext, Results); + + // Look in the superclass. + if (IFace->getSuperClass()) + AddObjCProperties(IFace->getSuperClass(), CurContext, Results); + } else if (const ObjCCategoryDecl *Category + = dyn_cast<ObjCCategoryDecl>(Container)) { + // Look through protocols. + for (ObjCInterfaceDecl::protocol_iterator P = Category->protocol_begin(), + PEnd = Category->protocol_end(); + P != PEnd; ++P) + AddObjCProperties(*P, CurContext, Results); + } } void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, @@ -1099,11 +1196,13 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, ResultBuilder Results(*this, &ResultBuilder::IsMember); unsigned NextRank = 0; - + + Results.EnterNewScope(); if (const RecordType *Record = BaseType->getAs<RecordType>()) { - NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank, + // Access to a C/C++ class, struct, or union. + NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank, Record->getDecl(), Results); - + if (getLangOptions().CPlusPlus) { if (!Results.empty()) { // The "template" keyword can follow "->" or "." in the grammar. @@ -1117,27 +1216,63 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, break; } } - + if (IsDependent) Results.MaybeAddResult(Result("template", NextRank++)); } - + // We could have the start of a nested-name-specifier. Add those // results as well. Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); - CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank, + CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank, CurContext, Results); } + } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) { + // Objective-C property reference. - // Add macros - AddMacroResults(PP, NextRank, Results); + // Add property results based on our interface. + const ObjCObjectPointerType *ObjCPtr + = BaseType->getAsObjCInterfacePointerType(); + assert(ObjCPtr && "Non-NULL pointer guaranteed above!"); + AddObjCProperties(ObjCPtr->getInterfaceDecl(), CurContext, Results); - // Hand off the results found for code completion. - HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); + // Add properties from the protocols in a qualified interface. + for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(), + E = ObjCPtr->qual_end(); + I != E; ++I) + AddObjCProperties(*I, CurContext, Results); - // We're done! - return; + // FIXME: We could (should?) also look for "implicit" properties, identified + // only by the presence of nullary and unary selectors. + } else if ((IsArrow && BaseType->isObjCObjectPointerType()) || + (!IsArrow && BaseType->isObjCInterfaceType())) { + // Objective-C instance variable access. + ObjCInterfaceDecl *Class = 0; + if (const ObjCObjectPointerType *ObjCPtr + = BaseType->getAs<ObjCObjectPointerType>()) + Class = ObjCPtr->getInterfaceDecl(); + else + Class = BaseType->getAs<ObjCInterfaceType>()->getDecl(); + + // Add all ivars from this class and its superclasses. + for (; Class; Class = Class->getSuperClass()) { + for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(), + IVarEnd = Class->ivar_end(); + IVar != IVarEnd; ++IVar) + Results.MaybeAddResult(Result(*IVar, 0), CurContext); + } } + + // FIXME: How do we cope with isa? + + Results.ExitScope(); + + // Add macros + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, NextRank, Results); + + // Hand off the results found for code completion. + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { @@ -1177,8 +1312,9 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { NextRank, CurContext, Results); } - AddMacroResults(PP, NextRank, Results); - HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, NextRank, Results); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } void Sema::CodeCompleteCase(Scope *S) { @@ -1255,8 +1391,9 @@ void Sema::CodeCompleteCase(Scope *S) { } Results.ExitScope(); - AddMacroResults(PP, 1, Results); - HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, 1, Results); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } namespace { @@ -1328,7 +1465,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, if (Cand->Viable) Results.push_back(ResultCandidate(Cand->Function)); } - CodeCompleter->ProcessOverloadCandidates(NumArgs, Results.data(), + CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(), Results.size()); } @@ -1350,8 +1487,9 @@ void Sema::CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS, if (!Results.empty() && NNS->isDependent()) Results.MaybeAddResult(CodeCompleteConsumer::Result("template", NextRank)); - AddMacroResults(PP, NextRank + 1, Results); - HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, NextRank + 1, Results); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } void Sema::CodeCompleteUsing(Scope *S) { @@ -1371,8 +1509,9 @@ void Sema::CodeCompleteUsing(Scope *S) { 0, CurContext, Results); Results.ExitScope(); - AddMacroResults(PP, NextRank, Results); - HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, NextRank, Results); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } void Sema::CodeCompleteUsingDirective(Scope *S) { @@ -1386,8 +1525,9 @@ void Sema::CodeCompleteUsingDirective(Scope *S) { unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext, Results); Results.ExitScope(); - AddMacroResults(PP, NextRank, Results); - HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, NextRank, Results); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } void Sema::CodeCompleteNamespaceDecl(Scope *S) { @@ -1421,8 +1561,9 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { Results.ExitScope(); } - AddMacroResults(PP, 1, Results); - HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, 1, Results); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { @@ -1433,8 +1574,9 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias); unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext, Results); - AddMacroResults(PP, NextRank, Results); - HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, NextRank, Results); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } void Sema::CodeCompleteOperatorName(Scope *S) { @@ -1464,8 +1606,9 @@ void Sema::CodeCompleteOperatorName(Scope *S) { NextRank + 1, CurContext, Results); Results.ExitScope(); - AddMacroResults(PP, NextRank, Results); - HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, NextRank, Results); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } void Sema::CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) { @@ -1493,5 +1636,252 @@ void Sema::CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) { if (!(Attributes & ObjCDeclSpec::DQ_PR_getter)) Results.MaybeAddResult(CodeCompleteConsumer::Result("getter", 0)); Results.ExitScope(); - HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + +/// \brief Add all of the Objective-C methods in the given Objective-C +/// container to the set of results. +/// +/// The container will be a class, protocol, category, or implementation of +/// any of the above. This mether will recurse to include methods from +/// the superclasses of classes along with their categories, protocols, and +/// implementations. +/// +/// \param Container the container in which we'll look to find methods. +/// +/// \param WantInstance whether to add instance methods (only); if false, this +/// routine will add factory methods (only). +/// +/// \param CurContext the context in which we're performing the lookup that +/// finds methods. +/// +/// \param Results the structure into which we'll add results. +static void AddObjCMethods(ObjCContainerDecl *Container, + bool WantInstanceMethods, + DeclContext *CurContext, + ResultBuilder &Results) { + typedef CodeCompleteConsumer::Result Result; + for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), + MEnd = Container->meth_end(); + M != MEnd; ++M) { + if ((*M)->isInstanceMethod() == WantInstanceMethods) + Results.MaybeAddResult(Result(*M, 0), CurContext); + } + + ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container); + if (!IFace) + return; + + // Add methods in protocols. + const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + AddObjCMethods(*I, WantInstanceMethods, CurContext, Results); + + // Add methods in categories. + for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl; + CatDecl = CatDecl->getNextClassCategory()) { + AddObjCMethods(CatDecl, WantInstanceMethods, CurContext, Results); + + // Add a categories protocol methods. + const ObjCList<ObjCProtocolDecl> &Protocols + = CatDecl->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + AddObjCMethods(*I, WantInstanceMethods, CurContext, Results); + + // Add methods in category implementations. + if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation()) + AddObjCMethods(Impl, WantInstanceMethods, CurContext, Results); + } + + // Add methods in superclass. + if (IFace->getSuperClass()) + AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, CurContext, + Results); + + // Add methods in our implementation, if any. + if (ObjCImplementationDecl *Impl = IFace->getImplementation()) + AddObjCMethods(Impl, WantInstanceMethods, CurContext, Results); +} + +void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, + SourceLocation FNameLoc) { + typedef CodeCompleteConsumer::Result Result; + ObjCInterfaceDecl *CDecl = 0; + + if (FName->isStr("super")) { + // We're sending a message to "super". + if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { + // Figure out which interface we're in. + CDecl = CurMethod->getClassInterface(); + if (!CDecl) + return; + + // Find the superclass of this class. + CDecl = CDecl->getSuperClass(); + if (!CDecl) + return; + + if (CurMethod->isInstanceMethod()) { + // We are inside an instance method, which means that the message + // send [super ...] is actually calling an instance method on the + // current object. Build the super expression and handle this like + // an instance method. + QualType SuperTy = Context.getObjCInterfaceType(CDecl); + SuperTy = Context.getObjCObjectPointerType(SuperTy); + OwningExprResult Super + = Owned(new (Context) ObjCSuperExpr(FNameLoc, SuperTy)); + return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get()); + } + + // Okay, we're calling a factory method in our superclass. + } + } + + // If the given name refers to an interface type, retrieve the + // corresponding declaration. + if (!CDecl) + if (TypeTy *Ty = getTypeName(*FName, FNameLoc, S, 0, false)) { + QualType T = GetTypeFromParser(Ty, 0); + if (!T.isNull()) + if (const ObjCInterfaceType *Interface = T->getAs<ObjCInterfaceType>()) + CDecl = Interface->getDecl(); + } + + 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); + return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get()); + } + + // Add all of the factory methods in this Objective-C class, its protocols, + // superclasses, categories, implementation, etc. + ResultBuilder Results(*this); + Results.EnterNewScope(); + AddObjCMethods(CDecl, false, CurContext, Results); + Results.ExitScope(); + + // This also suppresses remaining diagnostics. + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver) { + typedef CodeCompleteConsumer::Result Result; + + Expr *RecExpr = static_cast<Expr *>(Receiver); + QualType RecType = RecExpr->getType(); + + // If necessary, apply function/array conversion to the receiver. + // C99 6.7.5.3p[7,8]. + DefaultFunctionArrayConversion(RecExpr); + QualType ReceiverType = RecExpr->getType(); + + if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType()) { + // FIXME: We're messaging 'id'. Do we actually want to look up every method + // in the universe? + return; + } + + // Build the set of methods we can see. + ResultBuilder Results(*this); + Results.EnterNewScope(); + + // Handle messages to Class. This really isn't a message to an instance + // method, so we treat it the same way we would treat a message send to a + // class method. + if (ReceiverType->isObjCClassType() || + ReceiverType->isObjCQualifiedClassType()) { + if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { + if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface()) + AddObjCMethods(ClassDecl, false, CurContext, Results); + } + } + // Handle messages to a qualified ID ("id<foo>"). + else if (const ObjCObjectPointerType *QualID + = ReceiverType->getAsObjCQualifiedIdType()) { + // Search protocols for instance methods. + for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(), + E = QualID->qual_end(); + I != E; ++I) + AddObjCMethods(*I, true, CurContext, Results); + } + // Handle messages to a pointer to interface type. + else if (const ObjCObjectPointerType *IFacePtr + = ReceiverType->getAsObjCInterfacePointerType()) { + // Search the class, its superclasses, etc., for instance methods. + AddObjCMethods(IFacePtr->getInterfaceDecl(), true, CurContext, Results); + + // Search protocols for instance methods. + for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(), + E = IFacePtr->qual_end(); + I != E; ++I) + AddObjCMethods(*I, true, CurContext, Results); + } + + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + +/// \brief Add all of the protocol declarations that we find in the given +/// (translation unit) context. +static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, + bool OnlyForwardDeclarations, + ResultBuilder &Results) { + typedef CodeCompleteConsumer::Result Result; + + for (DeclContext::decl_iterator D = Ctx->decls_begin(), + DEnd = Ctx->decls_end(); + D != DEnd; ++D) { + // Record any protocols we find. + if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D)) + if (!OnlyForwardDeclarations || Proto->isForwardDecl()) + Results.MaybeAddResult(Result(Proto, 0), CurContext); + + // Record any forward-declared protocols we find. + if (ObjCForwardProtocolDecl *Forward + = dyn_cast<ObjCForwardProtocolDecl>(*D)) { + for (ObjCForwardProtocolDecl::protocol_iterator + P = Forward->protocol_begin(), + PEnd = Forward->protocol_end(); + P != PEnd; ++P) + if (!OnlyForwardDeclarations || (*P)->isForwardDecl()) + Results.MaybeAddResult(Result(*P, 0), CurContext); + } + } +} + +void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, + unsigned NumProtocols) { + ResultBuilder Results(*this); + Results.EnterNewScope(); + + // Tell the result set to ignore all of the protocols we have + // already seen. + for (unsigned I = 0; I != NumProtocols; ++I) + if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first)) + Results.Ignore(Protocol); + + // Add all protocols. + AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false, + Results); + + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCProtocolDecl(Scope *) { + ResultBuilder Results(*this); + Results.EnterNewScope(); + + // Add all protocols. + AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true, + Results); + + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d89cb5f..57c101b 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "Lookup.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" @@ -24,6 +25,7 @@ #include "clang/AST/StmtObjC.h" #include "clang/Parse/DeclSpec.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/Template.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -86,13 +88,14 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, II, SS->getRange()).getAsOpaquePtr(); } - LookupResult Result; - LookupParsedName(Result, S, SS, &II, LookupOrdinaryName, false, false); + LookupResult Result(*this, &II, NameLoc, LookupOrdinaryName); + LookupParsedName(Result, S, SS, false); NamedDecl *IIDecl = 0; - switch (Result.getKind()) { + switch (Result.getResultKind()) { case LookupResult::NotFound: case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: return 0; case LookupResult::Ambiguous: @@ -101,8 +104,10 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // diagnose the error then. If we don't do this, then the error // about hiding the type will be immediately followed by an error // that only makes sense if the identifier was treated like a type. - if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) + if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) { + Result.suppressDiagnostics(); return 0; + } // Look to see if we have a type anywhere in the list of results. for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end(); @@ -122,6 +127,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // perform this lookup again (e.g., as an object name), which // will produce the ambiguity, or will complain that it expected // a type name. + Result.suppressDiagnostics(); return 0; } @@ -129,7 +135,6 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // ambiguity and then return that type. This might be the right // answer, or it might not be, but it suppresses any attempt to // perform the name lookup again. - DiagnoseAmbiguousLookup(Result, DeclarationName(&II), NameLoc); break; case LookupResult::Found: @@ -142,7 +147,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, QualType T; if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) { DiagnoseUseOfDecl(IIDecl, NameLoc); - + // C++ [temp.local]p2: // Within the scope of a class template specialization or // partial specialization, when the injected-class-name is @@ -162,10 +167,16 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, T = getQualifiedNameType(*SS, T); } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { - DiagnoseUseOfDecl(IIDecl, NameLoc); T = Context.getObjCInterfaceType(IDecl); - } else + } else if (UnresolvedUsingTypenameDecl *UUDecl = + dyn_cast<UnresolvedUsingTypenameDecl>(IIDecl)) { + // FIXME: preserve source structure information. + T = Context.getTypenameType(UUDecl->getTargetNestedNameSpecifier(), &II); + } else { + // If it's not plausibly a type, suppress diagnostics. + Result.suppressDiagnostics(); return 0; + } return T.getAsOpaquePtr(); } @@ -177,9 +188,10 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, /// where the user forgot to specify the tag. DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { // Do a tag name lookup in this scope. - LookupResult R; - LookupName(R, S, &II, LookupTagName, false, false); - if (R.getKind() == LookupResult::Found) + LookupResult R(*this, &II, SourceLocation(), LookupTagName); + LookupName(R, S, false); + R.suppressDiagnostics(); + if (R.getResultKind() == LookupResult::Found) if (const TagDecl *TD = dyn_cast<TagDecl>(R.getAsSingleDecl(Context))) { switch (TD->getTagKind()) { case TagDecl::TK_struct: return DeclSpec::TST_struct; @@ -384,6 +396,26 @@ bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) { return IdResolver.isDeclInScope(D, Ctx, Context, S); } +static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { + if (D->isUsed() || D->hasAttr<UnusedAttr>()) + return false; + + if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { + if (const RecordType *RT = VD->getType()->getAs<RecordType>()) { + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { + if (!RD->hasTrivialConstructor()) + return false; + if (!RD->hasTrivialDestructor()) + return false; + } + } + } + + return (isa<VarDecl>(D) && !isa<ParmVarDecl>(D) && + !isa<ImplicitParamDecl>(D) && + D->getDeclContext()->isFunctionOrMethod()); +} + void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { if (S->decl_empty()) return; assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) && @@ -400,10 +432,8 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { if (!D->getDeclName()) continue; // Diagnose unused variables in this scope. - if (!D->isUsed() && !D->hasAttr<UnusedAttr>() && isa<VarDecl>(D) && - !isa<ParmVarDecl>(D) && !isa<ImplicitParamDecl>(D) && - D->getDeclContext()->isFunctionOrMethod()) - Diag(D->getLocation(), diag::warn_unused_variable) << D->getDeclName(); + if (ShouldDiagnoseUnusedDecl(D)) + Diag(D->getLocation(), diag::warn_unused_variable) << D->getDeclName(); // Remove this name from our lexical scope. IdResolver.RemoveDecl(D); @@ -1396,9 +1426,9 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, FEnd = AnonRecord->field_end(); F != FEnd; ++F) { if ((*F)->getDeclName()) { - LookupResult R; - LookupQualifiedName(R, Owner, (*F)->getDeclName(), - LookupOrdinaryName, true); + LookupResult R(*this, (*F)->getDeclName(), SourceLocation(), + LookupOrdinaryName, ForRedeclaration); + LookupQualifiedName(R, Owner); NamedDecl *PrevDecl = R.getAsSingleDecl(Context); if (PrevDecl && !isa<TagDecl>(PrevDecl)) { // C++ [class.union]p2: @@ -1651,7 +1681,7 @@ DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) { case UnqualifiedId::IK_TemplateId: { TemplateName TName - = TemplateName::getFromVoidPointer(Name.TemplateId->Template); + = TemplateName::getFromVoidPointer(Name.TemplateId->Template); if (TemplateDecl *Template = TName.getAsTemplateDecl()) return Template->getDeclName(); if (OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl()) @@ -1679,9 +1709,8 @@ static bool isNearlyMatchingFunction(ASTContext &Context, QualType DeclParamTy = Declaration->getParamDecl(Idx)->getType(); QualType DefParamTy = Definition->getParamDecl(Idx)->getType(); - DeclParamTy = Context.getCanonicalType(DeclParamTy.getNonReferenceType()); - DefParamTy = Context.getCanonicalType(DefParamTy.getNonReferenceType()); - if (DeclParamTy.getUnqualifiedType() != DefParamTy.getUnqualifiedType()) + if (!Context.hasSameUnqualifiedType(DeclParamTy.getNonReferenceType(), + DefParamTy.getNonReferenceType())) return false; } @@ -1766,10 +1795,10 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, NameKind = LookupRedeclarationWithLinkage; DC = CurContext; - LookupResult R; - LookupName(R, S, Name, NameKind, true, - NameKind == LookupRedeclarationWithLinkage, - D.getIdentifierLoc()); + LookupResult R(*this, Name, D.getIdentifierLoc(), NameKind, + ForRedeclaration); + + LookupName(R, S, NameKind == LookupRedeclarationWithLinkage); PrevDecl = R.getAsSingleDecl(Context); } else { // Something like "int foo::x;" DC = computeDeclContext(D.getCXXScopeSpec(), true); @@ -1790,8 +1819,9 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, RequireCompleteDeclContext(D.getCXXScopeSpec())) return DeclPtrTy(); - LookupResult Res; - LookupQualifiedName(Res, DC, Name, LookupOrdinaryName, true); + LookupResult Res(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName, + ForRedeclaration); + LookupQualifiedName(Res, DC); PrevDecl = Res.getAsSingleDecl(Context); // C++ 7.3.1.2p2: @@ -1821,17 +1851,22 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, if (isa<TranslationUnitDecl>(DC)) { Diag(D.getIdentifierLoc(), diag::err_invalid_declarator_global_scope) << Name << D.getCXXScopeSpec().getRange(); - } else if (!CurContext->Encloses(DC)) { - // The qualifying scope doesn't enclose the original declaration. - // Emit diagnostic based on current scope. - SourceLocation L = D.getIdentifierLoc(); - SourceRange R = D.getCXXScopeSpec().getRange(); - if (isa<FunctionDecl>(CurContext)) - Diag(L, diag::err_invalid_declarator_in_function) << Name << R; - else - Diag(L, diag::err_invalid_declarator_scope) - << Name << cast<NamedDecl>(DC) << R; - D.setInvalidType(); + } else { + DeclContext *Cur = CurContext; + while (isa<LinkageSpecDecl>(Cur)) + Cur = Cur->getParent(); + if (!Cur->Encloses(DC)) { + // The qualifying scope doesn't enclose the original declaration. + // Emit diagnostic based on current scope. + SourceLocation L = D.getIdentifierLoc(); + SourceRange R = D.getCXXScopeSpec().getRange(); + if (isa<FunctionDecl>(Cur)) + Diag(L, diag::err_invalid_declarator_in_function) << Name << R; + else + Diag(L, diag::err_invalid_declarator_scope) + << Name << cast<NamedDecl>(DC) << R; + D.setInvalidType(); + } } } @@ -2417,7 +2452,9 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, } static bool isUsingDecl(Decl *D) { - return isa<UsingDecl>(D) || isa<UnresolvedUsingDecl>(D); + return isa<UsingDecl>(D) || + isa<UnresolvedUsingTypenameDecl>(D) || + isa<UnresolvedUsingValueDecl>(D); } /// \brief Data used with FindOverriddenMethod @@ -2429,7 +2466,7 @@ struct FindOverriddenMethodData { /// \brief Member lookup function that determines whether a given C++ /// method overrides a method in a base class, to be used with /// CXXRecordDecl::lookupInBases(). -static bool FindOverriddenMethod(CXXBaseSpecifier *Specifier, +static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *UserData) { RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); @@ -2588,12 +2625,27 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, return 0; } + bool isStatic = SC == FunctionDecl::Static; + + // [class.free]p1: + // Any allocation function for a class T is a static member + // (even if not explicitly declared static). + if (Name.getCXXOverloadedOperator() == OO_New || + Name.getCXXOverloadedOperator() == OO_Array_New) + isStatic = true; + + // [class.free]p6 Any deallocation function for a class X is a static member + // (even if not explicitly declared static). + if (Name.getCXXOverloadedOperator() == OO_Delete || + Name.getCXXOverloadedOperator() == OO_Array_Delete) + isStatic = true; + // This is a C++ method declaration. NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC), D.getIdentifierLoc(), Name, R, DInfo, - (SC == FunctionDecl::Static), isInline); + isStatic, isInline); - isVirtualOkay = (SC != FunctionDecl::Static); + isVirtualOkay = !isStatic; } else { // Determine whether the function was written with a // prototype. This true when: @@ -2812,10 +2864,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, TemplateIdAnnotation *TemplateId = D.getName().TemplateId; ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), - TemplateId->getTemplateArgIsType(), TemplateId->NumArgs); translateTemplateArguments(TemplateArgsPtr, - TemplateId->getTemplateArgLocations(), TemplateArgs); TemplateArgsPtr.release(); @@ -2887,8 +2937,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, << Name << DC << D.getCXXScopeSpec().getRange(); NewFD->setInvalidDecl(); - LookupResult Prev; - LookupQualifiedName(Prev, DC, Name, LookupOrdinaryName, true); + LookupResult Prev(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName, + ForRedeclaration); + LookupQualifiedName(Prev, DC); assert(!Prev.isAmbiguous() && "Cannot have an ambiguity in previous-declaration lookup"); for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end(); @@ -3068,9 +3119,13 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, // C++-specific checks. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) { CheckConstructor(Constructor); - } else if (isa<CXXDestructorDecl>(NewFD)) { - CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent()); + } else if (CXXDestructorDecl *Destructor = + dyn_cast<CXXDestructorDecl>(NewFD)) { + CXXRecordDecl *Record = Destructor->getParent(); QualType ClassType = Context.getTypeDeclType(Record); + + // FIXME: Shouldn't we be able to perform thisc heck even when the class + // type is dependent? Both gcc and edg can handle that. if (!ClassType->isDependentType()) { DeclarationName Name = Context.DeclarationNames.getCXXDestructorName( @@ -3079,7 +3134,10 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, Diag(NewFD->getLocation(), diag::err_destructor_name); return NewFD->setInvalidDecl(); } + + CheckDestructor(Destructor); } + Record->setUserDeclaredDestructor(true); // C++ [class]p4: A POD-struct is an aggregate class that has [...] no // user-defined destructor. @@ -3257,8 +3315,13 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { return; } - if (!VDecl->getType()->isArrayType() && - RequireCompleteType(VDecl->getLocation(), VDecl->getType(), + // A definition must end up with a complete type, which means it must be + // complete with the restriction that an array type might be completed by the + // initializer; note that later code assumes this restriction. + QualType BaseDeclType = VDecl->getType(); + if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType)) + BaseDeclType = Array->getElementType(); + if (RequireCompleteType(VDecl->getLocation(), BaseDeclType, diag::err_typecheck_decl_incomplete_type)) { RealDecl->setInvalidDecl(); return; @@ -3433,6 +3496,16 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, return; } + // An array without size is an incomplete type, and there are no special + // rules in C++ to make such a definition acceptable. + if (getLangOptions().CPlusPlus && Type->isIncompleteArrayType() && + !Var->hasExternalStorage()) { + Diag(Var->getLocation(), + diag::err_typecheck_incomplete_array_needs_initializer); + Var->setInvalidDecl(); + return; + } + // C++ [temp.expl.spec]p15: // An explicit specialization of a static data member of a template is a // definition if the declaration includes an initializer; otherwise, it @@ -3563,7 +3636,7 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, // template <typename... Args> void f(Args... args) { // int vals[] = { args }; // } - const IncompleteArrayType *IAT = T->getAs<IncompleteArrayType>(); + const IncompleteArrayType *IAT = Context.getAsIncompleteArrayType(T); Expr *Init = IDecl->getInit(); if (IAT && Init && (Init->isTypeDependent() || Init->isValueDependent())) { @@ -3987,7 +4060,15 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body)); if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl)) - computeBaseOrMembersToDestroy(Destructor); + MarkBaseAndMemberDestructorsReferenced(Destructor); + + // If any errors have occurred, clear out any temporaries that may have + // been leftover. This ensures that these temporaries won't be picked up for + // deletion in some later function. + if (PP.getDiagnostics().hasErrorOccurred()) + ExprTemporaries.clear(); + + assert(ExprTemporaries.empty() && "Leftover temporaries in function"); return D; } @@ -4236,7 +4317,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, bool isStdBadAlloc = false; bool Invalid = false; - bool RedeclarationOnly = (TUK != TUK_Reference); + RedeclarationKind Redecl = (RedeclarationKind) (TUK != TUK_Reference); if (Name && SS.isNotEmpty()) { // We have a nested-name tag ('struct foo::bar'). @@ -4263,15 +4344,13 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, DC = computeDeclContext(SS, true); SearchDC = DC; // Look-up name inside 'foo::'. - LookupResult R; - LookupQualifiedName(R, DC, Name, LookupTagName, RedeclarationOnly); + LookupResult R(*this, Name, NameLoc, LookupTagName, Redecl); + LookupQualifiedName(R, DC); - if (R.isAmbiguous()) { - DiagnoseAmbiguousLookup(R, Name, NameLoc, SS.getRange()); + if (R.isAmbiguous()) return DeclPtrTy(); - } - if (R.getKind() == LookupResult::Found) + if (R.getResultKind() == LookupResult::Found) PrevDecl = dyn_cast<TagDecl>(R.getFoundDecl()); // A tag 'foo::bar' must already exist. @@ -4287,10 +4366,9 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // FIXME: We're looking into outer scopes here, even when we // shouldn't be. Doing so can result in ambiguities that we // shouldn't be diagnosing. - LookupResult R; - LookupName(R, S, Name, LookupTagName, RedeclarationOnly); + LookupResult R(*this, Name, NameLoc, LookupTagName, Redecl); + LookupName(R, S); if (R.isAmbiguous()) { - DiagnoseAmbiguousLookup(R, Name, NameLoc); // FIXME: This is not best way to recover from case like: // // struct S s; @@ -4552,8 +4630,9 @@ CreateNewDecl: // shall not be declared with the same name as a typedef-name // that is declared in that scope and refers to a type other // than the class or enumeration itself. - LookupResult Lookup; - LookupName(Lookup, S, Name, LookupOrdinaryName, true); + LookupResult Lookup(*this, Name, NameLoc, LookupOrdinaryName, + ForRedeclaration); + LookupName(Lookup, S); TypedefDecl *PrevTypedef = 0; if (NamedDecl *Prev = Lookup.getAsSingleDecl(Context)) PrevTypedef = dyn_cast<TypedefDecl>(Prev); @@ -4772,7 +4851,8 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); - NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName, true); + NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName, + ForRedeclaration); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. @@ -5157,7 +5237,8 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, DInfo, ac, (Expr *)BitfieldWidth); if (II) { - NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName, true); + NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName, + ForRedeclaration); if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S) && !isa<TagDecl>(PrevDecl)) { Diag(Loc, diag::err_duplicate_member) << II; @@ -5352,21 +5433,25 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, llvm::APSInt EnumVal(32); QualType EltTy; - if (Val && !Val->isTypeDependent()) { - // Make sure to promote the operand type to int. - UsualUnaryConversions(Val); - if (Val != val.get()) { - val.release(); - val = Val; - } + if (Val) { + if (Val->isTypeDependent()) + EltTy = Context.DependentTy; + else { + // Make sure to promote the operand type to int. + UsualUnaryConversions(Val); + if (Val != val.get()) { + val.release(); + val = Val; + } - // C99 6.7.2.2p2: Make sure we have an integer constant expression. - SourceLocation ExpLoc; - if (!Val->isValueDependent() && - VerifyIntegerConstantExpression(Val, &EnumVal)) { - Val = 0; - } else { - EltTy = Val->getType(); + // C99 6.7.2.2p2: Make sure we have an integer constant expression. + SourceLocation ExpLoc; + if (!Val->isValueDependent() && + VerifyIntegerConstantExpression(Val, &EnumVal)) { + Val = 0; + } else { + EltTy = Val->getType(); + } } } @@ -5388,6 +5473,8 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, } } + assert(!EltTy.isNull() && "Enum constant with NULL type"); + val.release(); return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy, Val, EnumVal); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 18f57da..c96ab46 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -862,7 +862,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { } else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) { // We ignore weak import on properties and methods return; - } else { + } else if (!(S.LangOpts.ObjCNonFragileABI && isa<ObjCInterfaceDecl>(D))) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << 2 /*variable and function*/; return; @@ -1008,6 +1008,38 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { } +static void HandleCDeclAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // Attribute has no arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + // Attribute can be applied only to functions. + if (!isa<FunctionDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 0 /*function*/; + return; + } + + // cdecl and fastcall attributes are mutually incompatible. + if (d->getAttr<FastCallAttr>()) { + S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) + << "cdecl" << "fastcall"; + return; + } + + // cdecl and stdcall attributes are mutually incompatible. + if (d->getAttr<StdCallAttr>()) { + S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) + << "cdecl" << "stdcall"; + return; + } + + d->addAttr(::new (S.Context) CDeclAttr()); +} + + static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { // Attribute has no arguments. if (Attr.getNumArgs() != 0) { @@ -1319,7 +1351,14 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { // FIXME: Do we need to bounds check? unsigned ArgIdx = Idx.getZExtValue() - 1; - if (HasImplicitThisParam) ArgIdx--; + if (HasImplicitThisParam) { + if (ArgIdx == 0) { + S.Diag(Attr.getLoc(), diag::err_format_attribute_not) + << "a string type" << IdxExpr->getSourceRange(); + return; + } + ArgIdx--; + } // make sure the format string is really a string QualType Ty = getFunctionOrMethodArgType(d, ArgIdx); @@ -1822,6 +1861,7 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, 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; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index b8977cf..237a869 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -12,15 +12,17 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "Lookup.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/TypeOrdering.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Parse/DeclSpec.h" +#include "clang/Parse/Template.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Lex/Preprocessor.h" -#include "clang/Parse/DeclSpec.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" #include <algorithm> // for std::equal @@ -264,9 +266,18 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { ParmVarDecl *NewParam = New->getParamDecl(p); if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) { + // FIXME: If the parameter doesn't have an identifier then the location + // points to the '=' which means that the fixit hint won't remove any + // extra spaces between the type and the '='. + SourceLocation Begin = NewParam->getLocation(); + if (NewParam->getIdentifier()) + Begin = PP.getLocForEndOfToken(Begin); + Diag(NewParam->getLocation(), diag::err_param_default_argument_redefinition) - << NewParam->getDefaultArgRange(); + << NewParam->getDefaultArgRange() + << CodeModificationHint::CreateRemoval(SourceRange(Begin, + NewParam->getLocEnd())); // Look for the function declaration where the default argument was // actually written, which may be a declaration prior to Old. @@ -577,7 +588,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, for (unsigned idx = 0; idx < NumBases; ++idx) { QualType NewBaseType = Context.getCanonicalType(Bases[idx]->getType()); - NewBaseType = NewBaseType.getUnqualifiedType(); + NewBaseType = NewBaseType.getLocalUnqualifiedType(); if (KnownBaseTypes[NewBaseType]) { // C++ [class.mi]p3: @@ -688,6 +699,8 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, (void)DerivationOkay; if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) { + if (InaccessibleBaseID == 0) + return false; // Check that the base class can be accessed. return CheckBaseClassAccess(Derived, Base, InaccessibleBaseID, Paths, Loc, Name); @@ -718,9 +731,11 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, bool Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, - SourceLocation Loc, SourceRange Range) { + SourceLocation Loc, SourceRange Range, + bool IgnoreAccess) { return CheckDerivedToBaseConversion(Derived, Base, - diag::err_conv_to_inaccessible_base, + IgnoreAccess ? 0 : + diag::err_conv_to_inaccessible_base, diag::err_ambiguous_derived_to_base_conv, Loc, Range, DeclarationName()); } @@ -1018,6 +1033,10 @@ Sema::MemInitResult Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, SourceLocation IdLoc, SourceLocation RParenLoc) { + // FIXME: CXXBaseOrMemberInitializer should only contain a single + // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. + ExprTemporaries.clear(); + // Diagnose value-uses of fields to initialize themselves, e.g. // foo(foo) // where foo is not also a parameter to the constructor. @@ -1088,6 +1107,11 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, return true; Args[0] = NewExp; } + + // FIXME: CXXBaseOrMemberInitializer should only contain a single + // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. + ExprTemporaries.clear(); + // FIXME: Perform direct initialization of the member. return new (Context) CXXBaseOrMemberInitializer(Member, (Expr **)Args, NumArgs, C, IdLoc, RParenLoc); @@ -1117,8 +1141,7 @@ Sema::BuildBaseInitializer(QualType BaseType, Expr **Args, const CXXBaseSpecifier *DirectBaseSpec = 0; for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); Base != ClassDecl->bases_end(); ++Base) { - if (Context.getCanonicalType(BaseType).getUnqualifiedType() == - Context.getCanonicalType(Base->getType()).getUnqualifiedType()) { + if (Context.hasSameUnqualifiedType(BaseType, Base->getType())) { // We found a direct base of this type. That's what we're // initializing. DirectBaseSpec = &*Base; @@ -1166,7 +1189,7 @@ Sema::BuildBaseInitializer(QualType BaseType, Expr **Args, CXXConstructorDecl *C = 0; if (!BaseType->isDependentType() && !HasDependentArg) { DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(BaseType)); + Context.getCanonicalType(BaseType).getUnqualifiedType()); ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); C = PerformInitializationByConstructor(BaseType, @@ -1182,22 +1205,26 @@ Sema::BuildBaseInitializer(QualType BaseType, Expr **Args, } } + // FIXME: CXXBaseOrMemberInitializer should only contain a single + // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. + ExprTemporaries.clear(); + return new (Context) CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, NumArgs, C, IdLoc, RParenLoc); } -void +bool Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, CXXBaseOrMemberInitializer **Initializers, unsigned NumInitializers, - llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases, - llvm::SmallVectorImpl<FieldDecl *>&Fields) { + bool IsImplicitConstructor) { // We need to build the initializer AST according to order of construction // and not what user specified in the Initializers list. CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor->getDeclContext()); llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit; llvm::DenseMap<const void *, CXXBaseOrMemberInitializer*> AllBaseFields; bool HasDependentBaseInit = false; + bool HadError = false; for (unsigned i = 0; i < NumInitializers; i++) { CXXBaseOrMemberInitializer *Member = Initializers[i]; @@ -1239,13 +1266,8 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, E = ClassDecl->vbases_end(); VBase != E; ++VBase) { if (VBase->getType()->isDependentType()) continue; - if (CXXBaseOrMemberInitializer *Value = - AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) { - CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); - assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null"); - if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context)) - MarkDeclarationReferenced(Value->getSourceLocation(), Ctor); + if (CXXBaseOrMemberInitializer *Value + = AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) { AllToInit.push_back(Value); } else { @@ -1254,7 +1276,12 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, assert(VBaseDecl && "SetBaseOrMemberInitializers - VBaseDecl null"); CXXConstructorDecl *Ctor = VBaseDecl->getDefaultConstructor(Context); if (!Ctor) { - Bases.push_back(VBase); + Diag(Constructor->getLocation(), diag::err_missing_default_ctor) + << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) + << 0 << VBase->getType(); + Diag(VBaseDecl->getLocation(), diag::note_previous_class_decl) + << Context.getTagDeclType(VBaseDecl); + HadError = true; continue; } @@ -1265,6 +1292,9 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, MarkDeclarationReferenced(Constructor->getLocation(), Ctor); + // FIXME: CXXBaseOrMemberInitializer should only contain a single + // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. + ExprTemporaries.clear(); CXXBaseOrMemberInitializer *Member = new (Context) CXXBaseOrMemberInitializer(VBase->getType(), CtorArgs.takeAs<Expr>(), @@ -1284,13 +1314,8 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, // Skip dependent types. if (Base->getType()->isDependentType()) continue; - if (CXXBaseOrMemberInitializer *Value = - AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) { - CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null"); - if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context)) - MarkDeclarationReferenced(Value->getSourceLocation(), Ctor); + if (CXXBaseOrMemberInitializer *Value + = AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) { AllToInit.push_back(Value); } else { @@ -1299,7 +1324,12 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null"); CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context); if (!Ctor) { - Bases.push_back(Base); + Diag(Constructor->getLocation(), diag::err_missing_default_ctor) + << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) + << 0 << Base->getType(); + Diag(BaseDecl->getLocation(), diag::note_previous_class_decl) + << Context.getTagDeclType(BaseDecl); + HadError = true; continue; } @@ -1310,6 +1340,9 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, MarkDeclarationReferenced(Constructor->getLocation(), Ctor); + // FIXME: CXXBaseOrMemberInitializer should only contain a single + // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. + ExprTemporaries.clear(); CXXBaseOrMemberInitializer *Member = new (Context) CXXBaseOrMemberInitializer(Base->getType(), CtorArgs.takeAs<Expr>(), @@ -1328,7 +1361,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, if (const RecordType *FieldClassType = Field->getType()->getAs<RecordType>()) { CXXRecordDecl *FieldClassDecl - = cast<CXXRecordDecl>(FieldClassType->getDecl()); + = cast<CXXRecordDecl>(FieldClassType->getDecl()); for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(), EA = FieldClassDecl->field_end(); FA != EA; FA++) { if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*FA)) { @@ -1345,37 +1378,49 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, continue; } if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*Field)) { - QualType FT = (*Field)->getType(); - if (const RecordType* RT = FT->getAs<RecordType>()) { - CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RT->getDecl()); - assert(FieldRecDecl && "SetBaseOrMemberInitializers - BaseDecl null"); - if (CXXConstructorDecl *Ctor = - FieldRecDecl->getDefaultConstructor(Context)) - MarkDeclarationReferenced(Value->getSourceLocation(), Ctor); - } AllToInit.push_back(Value); continue; } - if ((*Field)->getType()->isDependentType()) { - Fields.push_back(*Field); + if ((*Field)->getType()->isDependentType()) continue; - } QualType FT = Context.getBaseElementType((*Field)->getType()); if (const RecordType* RT = FT->getAs<RecordType>()) { CXXConstructorDecl *Ctor = cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context); if (!Ctor) { - Fields.push_back(*Field); + Diag(Constructor->getLocation(), diag::err_missing_default_ctor) + << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) + << 1 << (*Field)->getDeclName(); + Diag(Field->getLocation(), diag::note_field_decl); + Diag(RT->getDecl()->getLocation(), diag::note_previous_class_decl) + << Context.getTagDeclType(RT->getDecl()); + HadError = true; continue; } - + + if (FT.isConstQualified() && Ctor->isTrivial()) { + Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor) + << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) + << 1 << (*Field)->getDeclName(); + Diag((*Field)->getLocation(), diag::note_declared_at); + HadError = true; + } + + // Don't create initializers for trivial constructors, since they don't + // actually need to be run. + if (Ctor->isTrivial()) + continue; + ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this); if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0), Constructor->getLocation(), CtorArgs)) continue; + // FIXME: CXXBaseOrMemberInitializer should only contain a single + // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. + ExprTemporaries.clear(); CXXBaseOrMemberInitializer *Member = new (Context) CXXBaseOrMemberInitializer(*Field,CtorArgs.takeAs<Expr>(), CtorArgs.size(), Ctor, @@ -1383,23 +1428,21 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, SourceLocation()); AllToInit.push_back(Member); - if (Ctor) - MarkDeclarationReferenced(Constructor->getLocation(), Ctor); - if (FT.isConstQualified() && (!Ctor || Ctor->isTrivial())) { - Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor) - << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName(); - Diag((*Field)->getLocation(), diag::note_declared_at); - } + MarkDeclarationReferenced(Constructor->getLocation(), Ctor); } else if (FT->isReferenceType()) { Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor) - << Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getDeclName(); + << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) + << 0 << (*Field)->getDeclName(); Diag((*Field)->getLocation(), diag::note_declared_at); + HadError = true; } else if (FT.isConstQualified()) { Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor) - << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName(); + << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) + << 1 << (*Field)->getDeclName(); Diag((*Field)->getLocation(), diag::note_declared_at); + HadError = true; } } @@ -1413,29 +1456,8 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, for (unsigned Idx = 0; Idx < NumInitializers; ++Idx) baseOrMemberInitializers[Idx] = AllToInit[Idx]; } -} - -void -Sema::BuildBaseOrMemberInitializers(ASTContext &C, - CXXConstructorDecl *Constructor, - CXXBaseOrMemberInitializer **Initializers, - unsigned NumInitializers - ) { - llvm::SmallVector<CXXBaseSpecifier *, 4> Bases; - llvm::SmallVector<FieldDecl *, 4> Members; - SetBaseOrMemberInitializers(Constructor, - Initializers, NumInitializers, Bases, Members); - for (unsigned int i = 0; i < Bases.size(); i++) { - if (!Bases[i]->getType()->isDependentType()) - Diag(Bases[i]->getSourceRange().getBegin(), - diag::err_missing_default_constructor) << 0 << Bases[i]->getType(); - } - for (unsigned int i = 0; i < Members.size(); i++) { - if (!Members[i]->getType()->isDependentType()) - Diag(Members[i]->getLocation(), diag::err_missing_default_constructor) - << 1 << Members[i]->getType(); - } + return HadError; } static void *GetKeyForTopLevelField(FieldDecl *Field) { @@ -1462,7 +1484,7 @@ static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member, if (Member->isMemberInitializer()) { FieldDecl *Field = Member->getMember(); - // After BuildBaseOrMemberInitializers call, Field is the anonymous union + // After SetBaseOrMemberInitializers call, Field is the anonymous union // data member of the class. Data member used in the initializer list is // in AnonUnionMember field. if (MemberMaybeAnon && Field->isAnonymousStructOrUnion()) @@ -1527,9 +1549,9 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, return; } - BuildBaseOrMemberInitializers(Context, Constructor, + SetBaseOrMemberInitializers(Constructor, reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits), - NumMemInits); + NumMemInits, false); if (Constructor->isDependentContext()) return; @@ -1612,77 +1634,63 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, } void -Sema::computeBaseOrMembersToDestroy(CXXDestructorDecl *Destructor) { - CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Destructor->getDeclContext()); - llvm::SmallVector<uintptr_t, 32> AllToDestruct; +Sema::MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor) { + // Ignore dependent destructors. + if (Destructor->isDependentContext()) + return; + + CXXRecordDecl *ClassDecl = Destructor->getParent(); - for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(), - E = ClassDecl->vbases_end(); VBase != E; ++VBase) { - if (VBase->getType()->isDependentType()) + // Non-static data members. + for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(), + E = ClassDecl->field_end(); I != E; ++I) { + FieldDecl *Field = *I; + + QualType FieldType = Context.getBaseElementType(Field->getType()); + + const RecordType* RT = FieldType->getAs<RecordType>(); + if (!RT) continue; - // Skip over virtual bases which have trivial destructors. - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); - if (BaseClassDecl->hasTrivialDestructor()) + + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (FieldClassDecl->hasTrivialDestructor()) continue; - if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context)) - MarkDeclarationReferenced(Destructor->getLocation(), - const_cast<CXXDestructorDecl*>(Dtor)); - uintptr_t Member = - reinterpret_cast<uintptr_t>(VBase->getType().getTypePtr()) - | CXXDestructorDecl::VBASE; - AllToDestruct.push_back(Member); + const CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(Context); + MarkDeclarationReferenced(Destructor->getLocation(), + const_cast<CXXDestructorDecl*>(Dtor)); } - for (CXXRecordDecl::base_class_iterator Base = - ClassDecl->bases_begin(), + + // Bases. + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), E = ClassDecl->bases_end(); Base != E; ++Base) { + // Ignore virtual bases. if (Base->isVirtual()) continue; - if (Base->getType()->isDependentType()) - continue; - // Skip over virtual bases which have trivial destructors. + + // Ignore trivial destructors. CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); if (BaseClassDecl->hasTrivialDestructor()) continue; - if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context)) - MarkDeclarationReferenced(Destructor->getLocation(), - const_cast<CXXDestructorDecl*>(Dtor)); - uintptr_t Member = - reinterpret_cast<uintptr_t>(Base->getType().getTypePtr()) - | CXXDestructorDecl::DRCTNONVBASE; - AllToDestruct.push_back(Member); - } - - // non-static data members. - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), - E = ClassDecl->field_end(); Field != E; ++Field) { - QualType FieldType = Context.getBaseElementType((*Field)->getType()); - - if (const RecordType* RT = FieldType->getAs<RecordType>()) { - // Skip over virtual bases which have trivial destructors. - CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); - if (FieldClassDecl->hasTrivialDestructor()) - continue; - if (const CXXDestructorDecl *Dtor = - FieldClassDecl->getDestructor(Context)) - MarkDeclarationReferenced(Destructor->getLocation(), - const_cast<CXXDestructorDecl*>(Dtor)); - uintptr_t Member = reinterpret_cast<uintptr_t>(*Field); - AllToDestruct.push_back(Member); - } + + const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context); + MarkDeclarationReferenced(Destructor->getLocation(), + const_cast<CXXDestructorDecl*>(Dtor)); } - - unsigned NumDestructions = AllToDestruct.size(); - if (NumDestructions > 0) { - Destructor->setNumBaseOrMemberDestructions(NumDestructions); - uintptr_t *BaseOrMemberDestructions = - new (Context) uintptr_t [NumDestructions]; - // Insert in reverse order. - for (int Idx = NumDestructions-1, i=0 ; Idx >= 0; --Idx) - BaseOrMemberDestructions[i++] = AllToDestruct[Idx]; - Destructor->setBaseOrMemberDestructions(BaseOrMemberDestructions); + + // Virtual bases. + for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(), + E = ClassDecl->vbases_end(); VBase != E; ++VBase) { + // Ignore trivial destructors. + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); + if (BaseClassDecl->hasTrivialDestructor()) + continue; + + const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context); + MarkDeclarationReferenced(Destructor->getLocation(), + const_cast<CXXDestructorDecl*>(Dtor)); } } @@ -1694,9 +1702,7 @@ void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) { if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>())) - BuildBaseOrMemberInitializers(Context, - Constructor, - (CXXBaseOrMemberInitializer **)0, 0); + SetBaseOrMemberInitializers(Constructor, 0, 0, false); } namespace { @@ -1931,7 +1937,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, } if (RD->isAbstract()) - AbstractClassUsageDiagnoser(*this, RD); + (void)AbstractClassUsageDiagnoser(*this, RD); if (!RD->isDependentType() && !RD->isInvalidDecl()) AddImplicitlyDeclaredMembersToClass(RD); @@ -2334,13 +2340,18 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { if (!Constructor->isInvalidDecl() && ((Constructor->getNumParams() == 1) || (Constructor->getNumParams() > 1 && - Constructor->getParamDecl(1)->hasDefaultArg()))) { + Constructor->getParamDecl(1)->hasDefaultArg())) && + Constructor->getTemplateSpecializationKind() + != TSK_ImplicitInstantiation) { QualType ParamType = Constructor->getParamDecl(0)->getType(); QualType ClassTy = Context.getTagDeclType(ClassDecl); if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) { SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation(); Diag(ParamLoc, diag::err_constructor_byvalue_arg) << CodeModificationHint::CreateInsertion(ParamLoc, " const &"); + + // FIXME: Rather that making the constructor invalid, we should endeavor + // to fix the type. Constructor->setInvalidDecl(); } } @@ -2349,6 +2360,28 @@ 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) { + CXXRecordDecl *RD = Destructor->getParent(); + + if (Destructor->isVirtual()) { + SourceLocation Loc; + + if (!Destructor->isImplicit()) + Loc = Destructor->getLocation(); + else + Loc = RD->getLocation(); + + // If we have a virtual destructor, look up the deallocation function + FunctionDecl *OperatorDelete = 0; + DeclarationName Name = + Context.DeclarationNames.getCXXOperatorName(OO_Delete); + if (!FindDeallocationFunction(Loc, RD, Name, OperatorDelete)) + Destructor->setOperatorDelete(OperatorDelete); + } +} + static inline bool FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) { return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && @@ -2606,7 +2639,8 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // in that declarative region, it is treated as an original-namespace-name. NamedDecl *PrevDecl - = LookupSingleName(DeclRegionScope, II, LookupOrdinaryName, true); + = LookupSingleName(DeclRegionScope, II, LookupOrdinaryName, + ForRedeclaration); if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) { // This is an extended namespace definition. @@ -2714,14 +2748,14 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, UsingDirectiveDecl *UDir = 0; // Lookup namespace name. - LookupResult R; - LookupParsedName(R, S, &SS, NamespcName, LookupNamespaceName, false); - if (R.isAmbiguous()) { - DiagnoseAmbiguousLookup(R, NamespcName, IdentLoc); + LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName); + LookupParsedName(R, S, &SS); + if (R.isAmbiguous()) return DeclPtrTy(); - } + if (!R.empty()) { NamedDecl *NS = R.getFoundDecl(); + // FIXME: Namespace aliases! assert(isa<NamespaceDecl>(NS) && "expected namespace decl"); // C++ [namespace.udir]p1: // A using-directive specifies that the names in the nominated @@ -2776,7 +2810,8 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, const CXXScopeSpec &SS, UnqualifiedId &Name, AttributeList *AttrList, - bool IsTypeName) { + bool IsTypeName, + SourceLocation TypenameLoc) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); switch (Name.getKind()) { @@ -2802,9 +2837,11 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, } DeclarationName TargetName = GetNameFromUnqualifiedId(Name); - NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, + NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS, Name.getSourceRange().getBegin(), - TargetName, AttrList, IsTypeName); + TargetName, AttrList, + /* IsInstantiation */ false, + IsTypeName, TypenameLoc); if (UD) { PushOnScopeChains(UD, S); UD->setAccess(AS); @@ -2813,12 +2850,46 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, return DeclPtrTy::make(UD); } -NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc, +/// Builds a shadow declaration corresponding to a 'using' declaration. +static UsingShadowDecl *BuildUsingShadowDecl(Sema &SemaRef, Scope *S, + AccessSpecifier AS, + UsingDecl *UD, NamedDecl *Orig) { + // FIXME: diagnose hiding, collisions + + // If we resolved to another shadow declaration, just coalesce them. + if (isa<UsingShadowDecl>(Orig)) { + Orig = cast<UsingShadowDecl>(Orig)->getTargetDecl(); + assert(!isa<UsingShadowDecl>(Orig) && "nested shadow declaration"); + } + + UsingShadowDecl *Shadow + = UsingShadowDecl::Create(SemaRef.Context, SemaRef.CurContext, + UD->getLocation(), UD, Orig); + UD->addShadowDecl(Shadow); + + if (S) + SemaRef.PushOnScopeChains(Shadow, S); + else + SemaRef.CurContext->addDecl(Shadow); + Shadow->setAccess(AS); + + return Shadow; +} + +/// Builds a using declaration. +/// +/// \param IsInstantiation - Whether this call arises from an +/// instantiation of an unresolved using declaration. We treat +/// the lookup differently for these declarations. +NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, + SourceLocation UsingLoc, const CXXScopeSpec &SS, SourceLocation IdentLoc, DeclarationName Name, AttributeList *AttrList, - bool IsTypeName) { + bool IsInstantiation, + bool IsTypeName, + SourceLocation TypenameLoc) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); assert(IdentLoc.isValid() && "Invalid TargetName location."); @@ -2833,14 +2904,20 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc, NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - if (isUnknownSpecialization(SS)) { - return UnresolvedUsingDecl::Create(Context, CurContext, UsingLoc, - SS.getRange(), NNS, - IdentLoc, Name, IsTypeName); + DeclContext *LookupContext = computeDeclContext(SS); + if (!LookupContext) { + if (IsTypeName) { + return UnresolvedUsingTypenameDecl::Create(Context, CurContext, + UsingLoc, TypenameLoc, + SS.getRange(), NNS, + IdentLoc, Name); + } else { + return UnresolvedUsingValueDecl::Create(Context, CurContext, + UsingLoc, SS.getRange(), NNS, + IdentLoc, Name); + } } - DeclContext *LookupContext = 0; - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) { // C++0x N2914 [namespace.udecl]p3: // A using-declaration used as a member-declaration shall refer to a member @@ -2848,37 +2925,36 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc, // anonymous union that is a member of a base class of the class being // defined, or shall refer to an enumerator for an enumeration type that is // a member of a base class of the class being defined. - const Type *Ty = NNS->getAsType(); - if (!Ty || !IsDerivedFrom(Context.getTagDeclType(RD), QualType(Ty, 0))) { + + CXXRecordDecl *LookupRD = dyn_cast<CXXRecordDecl>(LookupContext); + if (!LookupRD || !RD->isDerivedFrom(LookupRD)) { Diag(SS.getRange().getBegin(), diag::err_using_decl_nested_name_specifier_is_not_a_base_class) << NNS << RD->getDeclName(); return 0; } - - QualType BaseTy = Context.getCanonicalType(QualType(Ty, 0)); - LookupContext = BaseTy->getAs<RecordType>()->getDecl(); } else { // C++0x N2914 [namespace.udecl]p8: // A using-declaration for a class member shall be a member-declaration. - if (NNS->getKind() == NestedNameSpecifier::TypeSpec) { + if (isa<CXXRecordDecl>(LookupContext)) { Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_class_member) << SS.getRange(); return 0; } - - // C++0x N2914 [namespace.udecl]p9: - // In a using-declaration, a prefix :: refers to the global namespace. - if (NNS->getKind() == NestedNameSpecifier::Global) - LookupContext = Context.getTranslationUnitDecl(); - else - LookupContext = NNS->getAsNamespace(); } + // Look up the target name. Unlike most lookups, we do not want to + // hide tag declarations: tag names are visible through the using + // declaration even if hidden by ordinary names. + LookupResult R(*this, Name, IdentLoc, LookupOrdinaryName); - // Lookup target name. - LookupResult R; - LookupQualifiedName(R, LookupContext, Name, LookupOrdinaryName); + // We don't hide tags behind ordinary decls if we're in a + // non-dependent context, but in a dependent context, this is + // important for the stability of two-phase lookup. + if (!IsInstantiation) + R.setHideTags(false); + + LookupQualifiedName(R, LookupContext); if (R.empty()) { Diag(IdentLoc, diag::err_no_member) @@ -2886,24 +2962,49 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc, return 0; } - // FIXME: handle ambiguity? - NamedDecl *ND = R.getAsSingleDecl(Context); - - if (IsTypeName && !isa<TypeDecl>(ND)) { - Diag(IdentLoc, diag::err_using_typename_non_type); + if (R.isAmbiguous()) return 0; + + if (IsTypeName) { + // If we asked for a typename and got a non-type decl, error out. + if (R.getResultKind() != LookupResult::Found + || !isa<TypeDecl>(R.getFoundDecl())) { + Diag(IdentLoc, diag::err_using_typename_non_type); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + Diag((*I)->getUnderlyingDecl()->getLocation(), + diag::note_using_decl_target); + return 0; + } + } else { + // If we asked for a non-typename and we got a type, error out, + // but only if this is an instantiation of an unresolved using + // decl. Otherwise just silently find the type name. + if (IsInstantiation && + R.getResultKind() == LookupResult::Found && + isa<TypeDecl>(R.getFoundDecl())) { + Diag(IdentLoc, diag::err_using_dependent_value_is_type); + Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target); + return 0; + } } // C++0x N2914 [namespace.udecl]p6: // A using-declaration shall not name a namespace. - if (isa<NamespaceDecl>(ND)) { + if (R.getResultKind() == LookupResult::Found + && isa<NamespaceDecl>(R.getFoundDecl())) { Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace) << SS.getRange(); return 0; } - return UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(), - ND->getLocation(), UsingLoc, ND, NNS, IsTypeName); + UsingDecl *UD = UsingDecl::Create(Context, CurContext, IdentLoc, + SS.getRange(), UsingLoc, NNS, Name, + IsTypeName); + + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + BuildUsingShadowDecl(*this, S, AS, UD, *I); + + return UD; } /// getNamespaceDecl - Returns the namespace a decl represents. If the decl @@ -2923,12 +3024,12 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, IdentifierInfo *Ident) { // Lookup the namespace name. - LookupResult R; - LookupParsedName(R, S, &SS, Ident, LookupNamespaceName, false); + LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName); + LookupParsedName(R, S, &SS); // Check if we have a previous declaration with the same name. if (NamedDecl *PrevDecl - = LookupSingleName(S, Alias, LookupOrdinaryName, true)) { + = LookupSingleName(S, Alias, LookupOrdinaryName, ForRedeclaration)) { if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) { // We already have an alias with the same name that points to the same // namespace, so don't create a new one. @@ -2944,10 +3045,8 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, return DeclPtrTy(); } - if (R.isAmbiguous()) { - DiagnoseAmbiguousLookup(R, Ident, IdentLoc); + if (R.isAmbiguous()) return DeclPtrTy(); - } if (R.empty()) { Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange(); @@ -2973,76 +3072,22 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor->getDeclContext()); assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); - // Before the implicitly-declared default constructor for a class is - // implicitly defined, all the implicitly-declared default constructors - // for its base class and its non-static data members shall have been - // implicitly defined. - bool err = false; - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), - E = ClassDecl->bases_end(); Base != E; ++Base) { - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - if (!BaseClassDecl->hasTrivialConstructor()) { - if (CXXConstructorDecl *BaseCtor = - BaseClassDecl->getDefaultConstructor(Context)) - MarkDeclarationReferenced(CurrentLocation, BaseCtor); - else { - Diag(CurrentLocation, diag::err_defining_default_ctor) - << Context.getTagDeclType(ClassDecl) << 0 - << Context.getTagDeclType(BaseClassDecl); - Diag(BaseClassDecl->getLocation(), diag::note_previous_class_decl) - << Context.getTagDeclType(BaseClassDecl); - err = true; - } - } - } - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), - E = ClassDecl->field_end(); Field != E; ++Field) { - QualType FieldType = Context.getCanonicalType((*Field)->getType()); - if (const ArrayType *Array = Context.getAsArrayType(FieldType)) - FieldType = Array->getElementType(); - if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { - CXXRecordDecl *FieldClassDecl - = cast<CXXRecordDecl>(FieldClassType->getDecl()); - if (!FieldClassDecl->hasTrivialConstructor()) { - if (CXXConstructorDecl *FieldCtor = - FieldClassDecl->getDefaultConstructor(Context)) - MarkDeclarationReferenced(CurrentLocation, FieldCtor); - else { - Diag(CurrentLocation, diag::err_defining_default_ctor) - << Context.getTagDeclType(ClassDecl) << 1 << - Context.getTagDeclType(FieldClassDecl); - Diag((*Field)->getLocation(), diag::note_field_decl); - Diag(FieldClassDecl->getLocation(), diag::note_previous_class_decl) - << Context.getTagDeclType(FieldClassDecl); - err = true; - } - } - } else if (FieldType->isReferenceType()) { - Diag(CurrentLocation, diag::err_unintialized_member) - << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName(); - Diag((*Field)->getLocation(), diag::note_declared_at); - err = true; - } else if (FieldType.isConstQualified()) { - Diag(CurrentLocation, diag::err_unintialized_member) - << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName(); - Diag((*Field)->getLocation(), diag::note_declared_at); - err = true; - } - } - if (!err) - Constructor->setUsed(); - else + + if (SetBaseOrMemberInitializers(Constructor, 0, 0, true)) { + Diag(CurrentLocation, diag::note_ctor_synthesized_at) + << Context.getTagDeclType(ClassDecl); Constructor->setInvalidDecl(); + } else { + Constructor->setUsed(); + } + return; } void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, CXXDestructorDecl *Destructor) { assert((Destructor->isImplicit() && !Destructor->isUsed()) && "DefineImplicitDestructor - call it for implicit default dtor"); - - CXXRecordDecl *ClassDecl - = cast<CXXRecordDecl>(Destructor->getDeclContext()); + CXXRecordDecl *ClassDecl = Destructor->getParent(); assert(ClassDecl && "DefineImplicitDestructor - invalid destructor"); // C++ [class.dtor] p5 // Before the implicitly-declared default destructor for a class is @@ -3399,6 +3444,107 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, /*DirectInit=*/true); } +/// \brief Add the applicable constructor candidates for an initialization +/// by constructor. +static void AddConstructorInitializationCandidates(Sema &SemaRef, + QualType ClassType, + Expr **Args, + unsigned NumArgs, + Sema::InitializationKind Kind, + OverloadCandidateSet &CandidateSet) { + // C++ [dcl.init]p14: + // If the initialization is direct-initialization, or if it is + // copy-initialization where the cv-unqualified version of the + // source type is the same class as, or a derived class of, the + // class of the destination, constructors are considered. The + // applicable constructors are enumerated (13.3.1.3), and the + // best one is chosen through overload resolution (13.3). The + // constructor so selected is called to initialize the object, + // with the initializer expression(s) as its argument(s). If no + // constructor applies, or the overload resolution is ambiguous, + // the initialization is ill-formed. + const RecordType *ClassRec = ClassType->getAs<RecordType>(); + assert(ClassRec && "Can only initialize a class type here"); + + // FIXME: When we decide not to synthesize the implicitly-declared + // constructors, we'll need to make them appear here. + + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl()); + DeclarationName ConstructorName + = SemaRef.Context.DeclarationNames.getCXXConstructorName( + SemaRef.Context.getCanonicalType(ClassType).getUnqualifiedType()); + DeclContext::lookup_const_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName); + Con != ConEnd; ++Con) { + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl= dyn_cast<FunctionTemplateDecl>(*Con); + if (ConstructorTmpl) + Constructor + = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl()); + else + Constructor = cast<CXXConstructorDecl>(*Con); + + if ((Kind == Sema::IK_Direct) || + (Kind == Sema::IK_Copy && + Constructor->isConvertingConstructor(/*AllowExplicit=*/false)) || + (Kind == Sema::IK_Default && Constructor->isDefaultConstructor())) { + if (ConstructorTmpl) + SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0, + Args, NumArgs, CandidateSet); + else + SemaRef.AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet); + } + } +} + +/// \brief Attempt to perform initialization by constructor +/// (C++ [dcl.init]p14), which may occur as part of direct-initialization or +/// copy-initialization. +/// +/// This routine determines whether initialization by constructor is possible, +/// but it does not emit any diagnostics in the case where the initialization +/// is ill-formed. +/// +/// \param ClassType the type of the object being initialized, which must have +/// class type. +/// +/// \param Args the arguments provided to initialize the object +/// +/// \param NumArgs the number of arguments provided to initialize the object +/// +/// \param Kind the type of initialization being performed +/// +/// \returns the constructor used to initialize the object, if successful. +/// Otherwise, emits a diagnostic and returns NULL. +CXXConstructorDecl * +Sema::TryInitializationByConstructor(QualType ClassType, + Expr **Args, unsigned NumArgs, + SourceLocation Loc, + InitializationKind Kind) { + // Build the overload candidate set + OverloadCandidateSet CandidateSet; + AddConstructorInitializationCandidates(*this, ClassType, Args, NumArgs, Kind, + CandidateSet); + + // Determine whether we found a constructor we can use. + OverloadCandidateSet::iterator Best; + switch (BestViableFunction(CandidateSet, Loc, Best)) { + case OR_Success: + case OR_Deleted: + // We found a constructor. Return it. + return cast<CXXConstructorDecl>(Best->Function); + + case OR_No_Viable_Function: + case OR_Ambiguous: + // Overload resolution failed. Return nothing. + return 0; + } + + // Silence GCC warning + return 0; +} + /// \brief Perform initialization by constructor (C++ [dcl.init]p14), which /// may occur as part of direct-initialization or copy-initialization. /// @@ -3428,55 +3574,13 @@ Sema::PerformInitializationByConstructor(QualType ClassType, DeclarationName InitEntity, InitializationKind Kind, ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs) { - const RecordType *ClassRec = ClassType->getAs<RecordType>(); - assert(ClassRec && "Can only initialize a class type here"); + + // Build the overload candidate set Expr **Args = (Expr **)ArgsPtr.get(); unsigned NumArgs = ArgsPtr.size(); - - // C++ [dcl.init]p14: - // If the initialization is direct-initialization, or if it is - // copy-initialization where the cv-unqualified version of the - // source type is the same class as, or a derived class of, the - // class of the destination, constructors are considered. The - // applicable constructors are enumerated (13.3.1.3), and the - // best one is chosen through overload resolution (13.3). The - // constructor so selected is called to initialize the object, - // with the initializer expression(s) as its argument(s). If no - // constructor applies, or the overload resolution is ambiguous, - // the initialization is ill-formed. - const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl()); OverloadCandidateSet CandidateSet; - - // Add constructors to the overload set. - DeclarationName ConstructorName - = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(ClassType.getUnqualifiedType())); - DeclContext::lookup_const_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName); - Con != ConEnd; ++Con) { - // Find the constructor (which may be a template). - CXXConstructorDecl *Constructor = 0; - FunctionTemplateDecl *ConstructorTmpl= dyn_cast<FunctionTemplateDecl>(*Con); - if (ConstructorTmpl) - Constructor - = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl()); - else - Constructor = cast<CXXConstructorDecl>(*Con); - - if ((Kind == IK_Direct) || - (Kind == IK_Copy && - Constructor->isConvertingConstructor(/*AllowExplicit=*/false)) || - (Kind == IK_Default && Constructor->isDefaultConstructor())) { - if (ConstructorTmpl) - AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0, - Args, NumArgs, CandidateSet); - else - AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet); - } - } - - // FIXME: When we decide not to synthesize the implicitly-declared - // constructors, we'll need to make them appear here. + AddConstructorInitializationCandidates(*this, ClassType, Args, NumArgs, Kind, + CandidateSet); OverloadCandidateSet::iterator Best; switch (BestViableFunction(CandidateSet, Loc, Best)) { @@ -3613,8 +3717,8 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, QualType T1 = Context.getCanonicalType(OrigT1); QualType T2 = Context.getCanonicalType(OrigT2); - QualType UnqualT1 = T1.getUnqualifiedType(); - QualType UnqualT2 = T2.getUnqualifiedType(); + QualType UnqualT1 = T1.getLocalUnqualifiedType(); + QualType UnqualT2 = T2.getLocalUnqualifiedType(); // C++ [dcl.init.ref]p4: // Given types "cv1 T1" and "cv2 T2," "cv1 T1" is @@ -3663,12 +3767,15 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, /// When @p AllowExplicit, we also permit explicit user-defined /// conversion functions. /// When @p ForceRValue, we unconditionally treat the initializer as an rvalue. +/// When @p IgnoreBaseAccess, we don't do access control on to-base conversion. +/// This is used when this is called from a C-style cast. bool Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, SourceLocation DeclLoc, bool SuppressUserConversions, bool AllowExplicit, bool ForceRValue, - ImplicitConversionSequence *ICS) { + ImplicitConversionSequence *ICS, + bool IgnoreBaseAccess) { assert(DeclType->isReferenceType() && "Reference init needs a reference"); QualType T1 = DeclType->getAs<ReferenceType>()->getPointeeType(); @@ -3827,6 +3934,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, ICS->UserDefined.Before = Best->Conversions[0].Standard; ICS->UserDefined.After = Best->FinalConversion; ICS->UserDefined.ConversionFunction = Best->Function; + ICS->UserDefined.EllipsisConversion = false; assert(ICS->UserDefined.After.ReferenceBinding && ICS->UserDefined.After.DirectBinding && "Expected a direct reference binding!"); @@ -3882,7 +3990,8 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, // actually happens. if (DerivedToBase) return CheckDerivedToBaseConversion(T2, T1, DeclLoc, - Init->getSourceRange()); + Init->getSourceRange(), + IgnoreBaseAccess); else return false; } @@ -4051,9 +4160,28 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { // found in the rest of this subclause do not apply to them unless // explicitly stated in 3.7.3. // FIXME: Write a separate routine for checking this. For now, just allow it. - if (Op == OO_New || Op == OO_Array_New || - Op == OO_Delete || Op == OO_Array_Delete) + if (Op == OO_Delete || Op == OO_Array_Delete) return false; + + if (Op == OO_New || Op == OO_Array_New) { + bool ret = false; + if (FunctionDecl::param_iterator Param = FnDecl->param_begin()) { + QualType SizeTy = Context.getCanonicalType(Context.getSizeType()); + QualType T = Context.getCanonicalType((*Param)->getType()); + if (!T->isDependentType() && SizeTy != T) { + Diag(FnDecl->getLocation(), + diag::err_operator_new_param_type) << FnDecl->getDeclName() + << SizeTy; + ret = true; + } + } + QualType ResultTy = Context.getCanonicalType(FnDecl->getResultType()); + if (!ResultTy->isDependentType() && ResultTy != Context.VoidPtrTy) + return Diag(FnDecl->getLocation(), + diag::err_operator_new_result_type) << FnDecl->getDeclName() + << static_cast<QualType>(Context.VoidPtrTy); + return ret; + } // C++ [over.oper]p6: // An operator function shall either be a non-static member @@ -4182,7 +4310,6 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { assert(isa<CXXMethodDecl>(FnDecl) && "Overloaded = not member, but not filtered."); CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl); - Method->setCopyAssignment(true); Method->getParent()->addedAssignmentOperator(Context, Method); } @@ -4549,8 +4676,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S, // FIXME: handle dependent contexts if (!DC) return DeclPtrTy(); - LookupResult R; - LookupQualifiedName(R, DC, Name, LookupOrdinaryName, true); + LookupResult R(*this, Name, Loc, LookupOrdinaryName, ForRedeclaration); + LookupQualifiedName(R, DC); PrevDecl = R.getAsSingleDecl(Context); // If searching in that context implicitly found a declaration in @@ -4584,8 +4711,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S, while (DC->isRecord()) DC = DC->getParent(); - LookupResult R; - LookupQualifiedName(R, DC, Name, LookupOrdinaryName, true); + LookupResult R(*this, Name, Loc, LookupOrdinaryName, ForRedeclaration); + LookupQualifiedName(R, DC); PrevDecl = R.getAsSingleDecl(Context); // TODO: decide what we think about using declarations. @@ -4697,7 +4824,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, QualType COldTy = Context.getCanonicalType(OldTy); if (CNewTy == COldTy && - CNewTy.getCVRQualifiers() == COldTy.getCVRQualifiers()) + CNewTy.getLocalCVRQualifiers() == COldTy.getLocalCVRQualifiers()) return false; // Check if the return types are covariant @@ -4726,7 +4853,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, return true; } - if (NewClassTy.getUnqualifiedType() != OldClassTy.getUnqualifiedType()) { + if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) { // Check if the new class derives from the old class. if (!IsDerivedFrom(NewClassTy, OldClassTy)) { Diag(New->getLocation(), @@ -4748,7 +4875,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, } // The qualifiers of the return types must be the same. - if (CNewTy.getCVRQualifiers() != COldTy.getCVRQualifiers()) { + if (CNewTy.getLocalCVRQualifiers() != COldTy.getLocalCVRQualifiers()) { Diag(New->getLocation(), diag::err_covariant_return_type_different_qualifications) << New->getDeclName() << NewTy << OldTy; diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 93f8d0d..0c5569c 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -112,6 +112,14 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, IDecl->setLocation(AtInterfaceLoc); IDecl->setForwardDecl(false); IDecl->setClassLoc(ClassLoc); + + // Since this ObjCInterfaceDecl was created by a forward declaration, + // we now add it to the DeclContext since it wasn't added before + // (see ActOnForwardClassDeclaration). + CurContext->addDecl(IDecl); + + if (AttrList) + ProcessDeclAttributeList(TUScope, IDecl, AttrList); } } else { IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, @@ -1113,10 +1121,46 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl, assert(false && "invalid ObjCContainerDecl type."); } +void +Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, + ObjCContainerDecl* IDecl) { + // Rules apply in non-GC mode only + if (getLangOptions().getGCMode() != LangOptions::NonGC) + return; + for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(), + E = IDecl->prop_end(); + I != E; ++I) { + ObjCPropertyDecl *Property = (*I); + unsigned Attributes = Property->getPropertyAttributes(); + // We only care about readwrite atomic property. + if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) || + !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite)) + continue; + if (const ObjCPropertyImplDecl *PIDecl + = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) { + if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) + continue; + ObjCMethodDecl *GetterMethod = + IMPDecl->getInstanceMethod(Property->getGetterName()); + ObjCMethodDecl *SetterMethod = + IMPDecl->getInstanceMethod(Property->getSetterName()); + if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) { + SourceLocation MethodLoc = + (GetterMethod ? GetterMethod->getLocation() + : SetterMethod->getLocation()); + Diag(MethodLoc, diag::warn_atomic_property_rule) + << Property->getIdentifier(); + Diag(Property->getLocation(), diag::note_property_declare); + } + } + } +} + /// ActOnForwardClassDeclaration - Action::DeclPtrTy Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, IdentifierInfo **IdentList, + SourceLocation *IdentLocs, unsigned NumElts) { llvm::SmallVector<ObjCInterfaceDecl*, 32> Interfaces; @@ -1153,18 +1197,23 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); if (!IDecl) { // Not already seen? Make a forward decl. IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, - IdentList[i], - // FIXME: need to get the 'real' - // identifier loc from the parser. - AtClassLoc, true); - PushOnScopeChains(IDecl, TUScope); + IdentList[i], IdentLocs[i], true); + + // Push the ObjCInterfaceDecl on the scope chain but do *not* add it to + // the current DeclContext. This prevents clients that walk DeclContext + // from seeing the imaginary ObjCInterfaceDecl until it is actually + // declared later (if at all). We also take care to explicitly make + // sure this declaration is visible for name lookup. + PushOnScopeChains(IDecl, TUScope, false); + CurContext->makeDeclVisibleInContext(IDecl, true); } Interfaces.push_back(IDecl); } + assert(Interfaces.size() == NumElts); ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc, - &Interfaces[0], + Interfaces.data(), IdentLocs, Interfaces.size()); CurContext->addDecl(CDecl); CheckObjCDeclScope(CDecl); @@ -1524,12 +1573,17 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl, // should be true. if (!ClassDecl) return; - + bool isInterfaceDeclKind = isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl) || isa<ObjCProtocolDecl>(ClassDecl); bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl); + if (!isInterfaceDeclKind && AtEndLoc.isInvalid()) { + AtEndLoc = ClassDecl->getLocation(); + Diag(AtEndLoc, diag::warn_missing_atend); + } + DeclContext *DC = dyn_cast<DeclContext>(ClassDecl); // FIXME: Remove these and use the ObjCContainerDecl/DeclContext. @@ -1608,8 +1662,10 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl, } if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) { IC->setAtEndLoc(AtEndLoc); - if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) + if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) { ImplMethodsVsClassMethods(IC, IDecl); + AtomicPropertySetterGetterRules(IC, IDecl); + } } else if (ObjCCategoryImplDecl* CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) { CatImplClass->setAtEndLoc(AtEndLoc); @@ -1910,13 +1966,12 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, // with continuation class's readwrite property attribute! unsigned PIkind = PIDecl->getPropertyAttributes(); if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { - unsigned assignRetainCopyNonatomic = - (ObjCPropertyDecl::OBJC_PR_assign | - ObjCPropertyDecl::OBJC_PR_retain | + unsigned retainCopyNonatomic = + (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_copy | ObjCPropertyDecl::OBJC_PR_nonatomic); - if ((Attributes & assignRetainCopyNonatomic) != - (PIkind & assignRetainCopyNonatomic)) { + if ((Attributes & retainCopyNonatomic) != + (PIkind & retainCopyNonatomic)) { Diag(AtLoc, diag::warn_property_attr_mismatch); Diag(PIDecl->getLocation(), diag::note_property_declare); } diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index bdd00b8..25af052 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -183,7 +183,7 @@ bool Sema::CheckExceptionSpecSubset( SubIsPointer = true; } bool SubIsClass = CanonicalSubT->isRecordType(); - CanonicalSubT = CanonicalSubT.getUnqualifiedType(); + CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType(); CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/false); @@ -205,7 +205,7 @@ bool Sema::CheckExceptionSpecSubset( continue; } } - CanonicalSuperT = CanonicalSuperT.getUnqualifiedType(); + CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType(); // If the types are the same, move on to the next type in the subset. if (CanonicalSubT == CanonicalSuperT) { Contained = true; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index f1d6f2b..4f08ffe 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "Lookup.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -25,6 +26,7 @@ #include "clang/Parse/DeclSpec.h" #include "clang/Parse/Designator.h" #include "clang/Parse/Scope.h" +#include "clang/Parse/Template.h" using namespace clang; @@ -622,14 +624,12 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, if (Name.getKind() == UnqualifiedId::IK_TemplateId) { ASTTemplateArgsPtr TemplateArgsPtr(*this, Name.TemplateId->getTemplateArgs(), - Name.TemplateId->getTemplateArgIsType(), Name.TemplateId->NumArgs); return ActOnTemplateIdExpr(SS, TemplateTy::make(Name.TemplateId->Template), Name.TemplateId->TemplateNameLoc, Name.TemplateId->LAngleLoc, TemplateArgsPtr, - Name.TemplateId->getTemplateArgLocations(), Name.TemplateId->RAngleLoc); } @@ -682,15 +682,11 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, isAddressOfOperand)); } - LookupResult Lookup; - LookupParsedName(Lookup, S, SS, Name, LookupOrdinaryName, false, true, Loc); + LookupResult Lookup(*this, Name, Loc, LookupOrdinaryName); + LookupParsedName(Lookup, S, SS, true); - if (Lookup.isAmbiguous()) { - DiagnoseAmbiguousLookup(Lookup, Name, Loc, - SS && SS->isSet() ? SS->getRange() - : SourceRange()); + if (Lookup.isAmbiguous()) return ExprError(); - } NamedDecl *D = Lookup.getAsSingleDecl(Context); @@ -814,22 +810,18 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // information to check this property. if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) { Scope *CheckS = S; - while (CheckS) { + while (CheckS && CheckS->getControlParent()) { if (CheckS->isWithinElse() && CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) { - if (Var->getType()->isBooleanType()) - ExprError(Diag(Loc, diag::warn_value_always_false) - << Var->getDeclName()); - else - ExprError(Diag(Loc, diag::warn_value_always_zero) - << Var->getDeclName()); + ExprError(Diag(Loc, diag::warn_value_always_zero) + << Var->getDeclName() + << (Var->getType()->isPointerType()? 2 : + Var->getType()->isBooleanType()? 1 : 0)); break; } - // Move up one more control parent to check again. - CheckS = CheckS->getControlParent(); - if (CheckS) - CheckS = CheckS->getParent(); + // Move to the parent of this scope. + CheckS = CheckS->getParent(); } } } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) { @@ -986,7 +978,7 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, else if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) return BuildDeclRefExpr(Template, Context.OverloadTy, Loc, false, false, SS); - else if (UnresolvedUsingDecl *UD = dyn_cast<UnresolvedUsingDecl>(D)) + else if (UnresolvedUsingValueDecl *UD = dyn_cast<UnresolvedUsingValueDecl>(D)) return BuildDeclRefExpr(UD, Context.DependentTy, Loc, /*TypeDependent=*/true, /*ValueDependent=*/true, SS); @@ -1441,10 +1433,6 @@ QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) { Action::OwningExprResult Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Kind, ExprArg Input) { - // Since this might be a postfix expression, get rid of ParenListExprs. - Input = MaybeConvertParenListExprToParenExpr(S, move(Input)); - Expr *Arg = (Expr *)Input.get(); - UnaryOperator::Opcode Opc; switch (Kind) { default: assert(0 && "Unknown unary op!"); @@ -1452,124 +1440,7 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, case tok::minusminus: Opc = UnaryOperator::PostDec; break; } - if (getLangOptions().CPlusPlus && - (Arg->getType()->isRecordType() || Arg->getType()->isEnumeralType())) { - // Which overloaded operator? - OverloadedOperatorKind OverOp = - (Opc == UnaryOperator::PostInc)? OO_PlusPlus : OO_MinusMinus; - - // C++ [over.inc]p1: - // - // [...] If the function is a member function with one - // parameter (which shall be of type int) or a non-member - // function with two parameters (the second of which shall be - // of type int), it defines the postfix increment operator ++ - // for objects of that type. When the postfix increment is - // called as a result of using the ++ operator, the int - // argument will have value zero. - Expr *Args[2] = { - Arg, - new (Context) IntegerLiteral(llvm::APInt(Context.Target.getIntWidth(), 0, - /*isSigned=*/true), Context.IntTy, SourceLocation()) - }; - - // Build the candidate set for overloading - OverloadCandidateSet CandidateSet; - AddOperatorCandidates(OverOp, S, OpLoc, Args, 2, CandidateSet); - - // Perform overload resolution. - OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, OpLoc, Best)) { - case OR_Success: { - // We found a built-in operator or an overloaded operator. - FunctionDecl *FnDecl = Best->Function; - - if (FnDecl) { - // We matched an overloaded operator. Build a call to that - // operator. - - // Convert the arguments. - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { - if (PerformObjectArgumentInitialization(Arg, Method)) - return ExprError(); - } else { - // Convert the arguments. - if (PerformCopyInitialization(Arg, - FnDecl->getParamDecl(0)->getType(), - "passing")) - return ExprError(); - } - - // Determine the result type - QualType ResultTy = FnDecl->getResultType().getNonReferenceType(); - - // Build the actual expression node. - Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), - SourceLocation()); - UsualUnaryConversions(FnExpr); - - Input.release(); - Args[0] = Arg; - - ExprOwningPtr<CXXOperatorCallExpr> - TheCall(this, new (Context) CXXOperatorCallExpr(Context, OverOp, - FnExpr, Args, 2, - ResultTy, OpLoc)); - - if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall.get(), - FnDecl)) - return ExprError(); - return Owned(TheCall.release()); - - } else { - // We matched a built-in operator. Convert the arguments, then - // break out so that we will build the appropriate built-in - // operator node. - if (PerformCopyInitialization(Arg, Best->BuiltinTypes.ParamTypes[0], - "passing")) - return ExprError(); - - break; - } - } - - case OR_No_Viable_Function: { - // No viable function; try checking this as a built-in operator, which - // will fail and provide a diagnostic. Then, print the overload - // candidates. - OwningExprResult Result = CreateBuiltinUnaryOp(OpLoc, Opc, move(Input)); - assert(Result.isInvalid() && - "C++ postfix-unary operator overloading is missing candidates!"); - if (Result.isInvalid()) - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); - - return move(Result); - } - - case OR_Ambiguous: - Diag(OpLoc, diag::err_ovl_ambiguous_oper) - << UnaryOperator::getOpcodeStr(Opc) - << Arg->getSourceRange(); - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); - return ExprError(); - - case OR_Deleted: - Diag(OpLoc, diag::err_ovl_deleted_oper) - << Best->Function->isDeleted() - << UnaryOperator::getOpcodeStr(Opc) - << Arg->getSourceRange(); - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); - return ExprError(); - } - - // Either we found no viable overloaded operator or we matched a - // built-in operator. In either case, fall through to trying to - // build a built-in operation. - } - - Input.release(); - Input = Arg; - return CreateBuiltinUnaryOp(OpLoc, Opc, move(Input)); + return BuildUnaryOp(S, OpLoc, Opc, move(Input)); } Action::OwningExprResult @@ -1886,6 +1757,38 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, DefaultFunctionArrayConversion(BaseExpr); QualType BaseType = BaseExpr->getType(); + + // If the user is trying to apply -> or . to a function pointer + // type, it's probably because the 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>()) { + if (const FunctionProtoType *Fun + = Ptr->getPointeeType()->getAs<FunctionProtoType>()) { + QualType ResultTy = Fun->getResultType(); + if (Fun->getNumArgs() == 0 && + ((OpKind == tok::period && ResultTy->isRecordType()) || + (OpKind == tok::arrow && ResultTy->isPointerType() && + ResultTy->getAs<PointerType>()->getPointeeType() + ->isRecordType()))) { + SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd()); + Diag(Loc, diag::err_member_reference_needs_call) + << QualType(Fun, 0) + << CodeModificationHint::CreateInsertion(Loc, "()"); + + OwningExprResult NewBase + = ActOnCallExpr(S, ExprArg(*this, BaseExpr), Loc, + MultiExprArg(*this, 0, 0), 0, Loc); + if (NewBase.isInvalid()) + return move(NewBase); + + BaseExpr = NewBase.takeAs<Expr>(); + DefaultFunctionArrayConversion(BaseExpr); + BaseType = BaseExpr->getType(); + } + } + } + // If this is an Objective-C pseudo-builtin and a definition is provided then // use that. if (BaseType->isObjCIdType()) { @@ -2048,17 +1951,14 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, } // The record definition is complete, now make sure the member is valid. - LookupResult Result; - LookupQualifiedName(Result, DC, MemberName, LookupMemberName, false); + 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()) { - DiagnoseAmbiguousLookup(Result, MemberName, MemberLoc, - BaseExpr->getSourceRange()); + if (Result.isAmbiguous()) return ExprError(); - } NamedDecl *MemberDecl = Result.getAsSingleDecl(Context); @@ -2356,16 +2256,6 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), MemberLoc, BaseExpr)); } - for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), - E = OPT->qual_end(); I != E; ++I) - if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { - // Check whether we can reference this property. - if (DiagnoseUseOfDecl(PD, MemberLoc)) - return ExprError(); - - return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), - MemberLoc, BaseExpr)); - } // If that failed, look for an "implicit" property by seeing if the nullary // selector is implemented. @@ -2441,18 +2331,6 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union) << BaseType << BaseExpr->getSourceRange(); - // If the user is trying to apply -> or . to a function or function - // pointer, it's probably because they forgot parentheses to call - // the function. Suggest the addition of those parentheses. - if (BaseType == Context.OverloadTy || - BaseType->isFunctionType() || - (BaseType->isPointerType() && - BaseType->getAs<PointerType>()->isFunctionType())) { - SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd()); - Diag(Loc, diag::note_member_reference_needs_call) - << CodeModificationHint::CreateInsertion(Loc, "()"); - } - return ExprError(); } @@ -2485,12 +2363,10 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg Base, // Translate the parser's template argument list in our AST format. ASTTemplateArgsPtr TemplateArgsPtr(*this, Member.TemplateId->getTemplateArgs(), - Member.TemplateId->getTemplateArgIsType(), Member.TemplateId->NumArgs); llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; translateTemplateArguments(TemplateArgsPtr, - Member.TemplateId->getTemplateArgLocations(), TemplateArgs); TemplateArgsPtr.release(); @@ -2639,6 +2515,9 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, // Pass the argument. if (PerformCopyInitialization(Arg, ProtoArgType, "passing")) return true; + + if (!ProtoArgType->isReferenceType()) + Arg = MaybeBindToTemporary(Arg).takeAs<Expr>(); } else { ParmVarDecl *Param = FDecl->getParamDecl(i); @@ -2663,7 +2542,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, CallType = VariadicMethod; // Promote the arguments (C99 6.5.2.2p7). - for (unsigned i = NumArgsInProto; i != NumArgs; i++) { + for (unsigned i = NumArgsInProto; i < NumArgs; i++) { Expr *Arg = Args[i]; Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType); Call->setArg(i, Arg); @@ -3054,8 +2933,7 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist, static CastExpr::CastKind getScalarCastKind(ASTContext &Context, QualType SrcTy, QualType DestTy) { - if (Context.getCanonicalType(SrcTy).getUnqualifiedType() == - Context.getCanonicalType(DestTy).getUnqualifiedType()) + if (Context.hasSameUnqualifiedType(SrcTy, DestTy)) return CastExpr::CK_NoOp; if (SrcTy->hasPointerRepresentation()) { @@ -3106,8 +2984,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr, } if (!castType->isScalarType() && !castType->isVectorType()) { - if (Context.getCanonicalType(castType).getUnqualifiedType() == - Context.getCanonicalType(castExpr->getType().getUnqualifiedType()) && + if (Context.hasSameUnqualifiedType(castType, castExpr->getType()) && (castType->isStructureType() || castType->isUnionType())) { // GCC struct/union extension: allow cast to self. // FIXME: Check that the cast destination type is complete. @@ -3123,8 +3000,8 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr, RecordDecl::field_iterator Field, FieldEnd; for (Field = RD->field_begin(), FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { - if (Context.getCanonicalType(Field->getType()).getUnqualifiedType() == - Context.getCanonicalType(castExpr->getType()).getUnqualifiedType()) { + if (Context.hasSameUnqualifiedType(Field->getType(), + castExpr->getType())) { Diag(TyR.getBegin(), diag::ext_typecheck_cast_to_union) << castExpr->getSourceRange(); break; @@ -3570,9 +3447,9 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); // Add qualifiers if necessary. - ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp); + ImpCastExprToType(RHS, destType, CastExpr::CK_NoOp); // Promote to void*. - ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast); + ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast); return destType; } @@ -3731,6 +3608,24 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) { return ConvTy; return IncompatiblePointerSign; } + + // If we are a multi-level pointer, it's possible that our issue is simply + // one of qualification - e.g. char ** -> const char ** is not allowed. If + // the eventual target type is the same and the pointers have the same + // level of indirection, this must be the issue. + if (lhptee->isPointerType() && rhptee->isPointerType()) { + do { + lhptee = lhptee->getAs<PointerType>()->getPointeeType(); + rhptee = rhptee->getAs<PointerType>()->getPointeeType(); + + lhptee = Context.getCanonicalType(lhptee); + rhptee = Context.getCanonicalType(rhptee); + } while (lhptee->isPointerType() && rhptee->isPointerType()); + + if (Context.hasSameUnqualifiedType(lhptee, rhptee)) + return IncompatibleNestedPointerQualifiers; + } + // General pointer incompatibility takes priority over qualifiers. return IncompatiblePointer; } @@ -3757,7 +3652,7 @@ Sema::CheckBlockPointerTypesForAssignment(QualType lhsType, AssignConvertType ConvTy = Compatible; // For blocks we enforce that qualifiers are identical. - if (lhptee.getCVRQualifiers() != rhptee.getCVRQualifiers()) + if (lhptee.getLocalCVRQualifiers() != rhptee.getLocalCVRQualifiers()) ConvTy = CompatiblePointerDiscardsQualifiers; if (!Context.typesAreCompatible(lhptee, rhptee)) @@ -4429,26 +4324,51 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, return LHSTy; } -/// Implements -Wsign-compare. +/// \brief Implements -Wsign-compare. +/// +/// \param lex the left-hand expression +/// \param rex the right-hand expression +/// \param OpLoc the location of the joining operator +/// \param Equality whether this is an "equality-like" join, which +/// suppresses the warning in some cases void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc, - const PartialDiagnostic &PD) { + const PartialDiagnostic &PD, bool Equality) { + // Don't warn if we're in an unevaluated context. + if (ExprEvalContext == Unevaluated) + return; + QualType lt = lex->getType(), rt = rex->getType(); // Only warn if both operands are integral. if (!lt->isIntegerType() || !rt->isIntegerType()) return; + // If either expression is value-dependent, don't warn. We'll get another + // chance at instantiation time. + if (lex->isValueDependent() || rex->isValueDependent()) + return; + // The rule is that the signed operand becomes unsigned, so isolate the // signed operand. - Expr *signedOperand; + Expr *signedOperand, *unsignedOperand; if (lt->isSignedIntegerType()) { if (rt->isSignedIntegerType()) return; signedOperand = lex; + unsignedOperand = rex; } else { if (!rt->isSignedIntegerType()) return; signedOperand = rex; + unsignedOperand = lex; } + // If the unsigned type is strictly smaller than the signed type, + // then (1) the result type will be signed and (2) the unsigned + // value will fit fully within the signed type, and thus the result + // of the comparison will be exact. + if (Context.getIntWidth(signedOperand->getType()) > + Context.getIntWidth(unsignedOperand->getType())) + return; + // If the value is a non-negative integer constant, then the // signed->unsigned conversion won't change it. llvm::APSInt value; @@ -4459,6 +4379,20 @@ void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc, return; } + if (Equality) { + // For (in)equality comparisons, if the unsigned operand is a + // constant which cannot collide with a overflowed signed operand, + // then reinterpreting the signed operand as unsigned will not + // change the result of the comparison. + if (unsignedOperand->isIntegerConstantExpr(value, Context)) { + assert(!value.isSigned() && "result of unsigned expression is signed"); + + // 2's complement: test the top bit. + if (value.isNonNegative()) + return; + } + } + Diag(OpLoc, PD) << lex->getType() << rex->getType() << lex->getSourceRange() << rex->getSourceRange(); @@ -4472,7 +4406,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) return CheckVectorCompareOperands(lex, rex, Loc, isRelational); - CheckSignCompare(lex, rex, Loc, diag::warn_mixed_sign_comparison); + CheckSignCompare(lex, rex, Loc, diag::warn_mixed_sign_comparison, + (Opc == BinaryOperator::EQ || Opc == BinaryOperator::NE)); // C99 6.5.8p3 / C99 6.5.9p4 if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType()) @@ -5637,7 +5572,8 @@ Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperator::Opcode Opc, ExprArg input) { Expr *Input = (Expr*)input.get(); - if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType()) { + if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType() && + Opc != UnaryOperator::Extension) { // Find all of the overloaded operators visible from this // point. We perform both an operator-name lookup from the local // scope and an argument-dependent lookup based on the types of @@ -5814,8 +5750,8 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, } } - LookupResult R; - LookupQualifiedName(R, RD, OC.U.IdentInfo, LookupMemberName); + LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName); + LookupQualifiedName(R, RD); FieldDecl *MemberDecl = dyn_cast_or_null<FieldDecl>(R.getAsSingleDecl(Context)); @@ -5828,7 +5764,7 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, // FIXME: Verify that MemberDecl isn't a bitfield. if (cast<RecordDecl>(MemberDecl->getDeclContext())->isAnonymousStructOrUnion()) { Res = BuildAnonymousStructUnionMemberReference( - SourceLocation(), MemberDecl, Res, SourceLocation()).takeAs<Expr>(); + OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs<Expr>(); } else { // MemberDecl->getType() doesn't get the right qualifiers, but it // doesn't matter here. @@ -6127,6 +6063,34 @@ Sema::OwningExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) { return Owned(new (Context) GNUNullExpr(Ty, TokenLoc)); } +static void +MakeObjCStringLiteralCodeModificationHint(Sema& SemaRef, + QualType DstType, + Expr *SrcExpr, + CodeModificationHint &Hint) { + if (!SemaRef.getLangOptions().ObjC1) + return; + + const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>(); + if (!PT) + return; + + // Check if the destination is of type 'id'. + if (!PT->isObjCIdType()) { + // Check if the destination is the 'NSString' interface. + const ObjCInterfaceDecl *ID = PT->getInterfaceDecl(); + if (!ID || !ID->getIdentifier()->isStr("NSString")) + return; + } + + // Strip off any parens and casts. + StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr->IgnoreParenCasts()); + if (!SL || SL->isWide()) + return; + + Hint = CodeModificationHint::CreateInsertion(SL->getLocStart(), "@"); +} + bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, SourceLocation Loc, QualType DstType, QualType SrcType, @@ -6134,6 +6098,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, // Decode the result (notice that AST's are still created for extensions). bool isInvalid = false; unsigned DiagKind; + CodeModificationHint Hint; + switch (ConvTy) { default: assert(0 && "Unknown conversion type"); case Compatible: return false; @@ -6144,6 +6110,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, DiagKind = diag::ext_typecheck_convert_int_pointer; break; case IncompatiblePointer: + MakeObjCStringLiteralCodeModificationHint(*this, DstType, SrcExpr, Hint); DiagKind = diag::ext_typecheck_convert_incompatible_pointer; break; case IncompatiblePointerSign: @@ -6167,6 +6134,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, return false; DiagKind = diag::ext_typecheck_convert_discards_qualifiers; break; + case IncompatibleNestedPointerQualifiers: + DiagKind = diag::ext_nested_pointer_qualifier_mismatch; + break; case IntToBlockPointer: DiagKind = diag::err_int_to_block_pointer; break; @@ -6188,7 +6158,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, } Diag(Loc, DiagKind) << DstType << SrcType << Flavor - << SrcExpr->getSourceRange(); + << SrcExpr->getSourceRange() << Hint; return isInvalid; } @@ -6405,11 +6375,29 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc, void Sema::DiagnoseAssignmentAsCondition(Expr *E) { SourceLocation Loc; + unsigned diagnostic = diag::warn_condition_is_assignment; + if (isa<BinaryOperator>(E)) { BinaryOperator *Op = cast<BinaryOperator>(E); if (Op->getOpcode() != BinaryOperator::Assign) return; + // Greylist some idioms by putting them into a warning subcategory. + if (ObjCMessageExpr *ME + = dyn_cast<ObjCMessageExpr>(Op->getRHS()->IgnoreParenCasts())) { + Selector Sel = ME->getSelector(); + + // self = [<foo> init...] + if (isSelfExpr(Op->getLHS()) + && Sel.getIdentifierInfoForSlot(0)->getName().startswith("init")) + diagnostic = diag::warn_condition_is_idiomatic_assignment; + + // <foo> = [<bar> nextObject] + else if (Sel.isUnarySelector() && + Sel.getIdentifierInfoForSlot(0)->getName() == "nextObject") + diagnostic = diag::warn_condition_is_idiomatic_assignment; + } + Loc = Op->getOperatorLoc(); } else if (isa<CXXOperatorCallExpr>(E)) { CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(E); @@ -6425,7 +6413,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { SourceLocation Open = E->getSourceRange().getBegin(); SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd()); - Diag(Loc, diag::warn_condition_is_assignment) + Diag(Loc, diagnostic) << E->getSourceRange() << CodeModificationHint::CreateInsertion(Open, "(") << CodeModificationHint::CreateInsertion(Close, ")"); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index dc57681..0eea169 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "Lookup.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/ExprCXX.h" @@ -34,8 +35,8 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, TyOrExpr = GetTypeFromParser(TyOrExpr).getAsOpaquePtr(); IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info"); - LookupResult R; - LookupQualifiedName(R, StdNamespace, TypeInfoII, LookupTagName); + LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName); + LookupQualifiedName(R, StdNamespace); Decl *TypeInfoDecl = R.getAsSingleDecl(Context); RecordDecl *TypeInfoRecordDecl = dyn_cast_or_null<RecordDecl>(TypeInfoDecl); if (!TypeInfoRecordDecl) @@ -424,14 +425,13 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, Expr **ConsArgs = (Expr**)ConstructorArgs.get(); const RecordType *RT; unsigned NumConsArgs = ConstructorArgs.size(); - + ASTOwningVector<&ActionBase::DeleteExpr> ConvertedConstructorArgs(*this); + if (AllocType->isDependentType() || Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) { // Skip all the checks. } else if ((RT = AllocType->getAs<RecordType>()) && !AllocType->isAggregateType()) { - ASTOwningVector<&ActionBase::DeleteExpr> ConvertedConstructorArgs(*this); - Constructor = PerformInitializationByConstructor( AllocType, move(ConstructorArgs), TypeLoc, @@ -568,8 +568,8 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, DeclarationName Name, Expr** Args, unsigned NumArgs, DeclContext *Ctx, bool AllowMissing, FunctionDecl *&Operator) { - LookupResult R; - LookupQualifiedName(R, Ctx, Name, LookupOrdinaryName); + LookupResult R(*this, Name, StartLoc, LookupOrdinaryName); + LookupQualifiedName(R, Ctx); if (R.empty()) { if (AllowMissing) return false; @@ -754,6 +754,57 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, ((DeclContext *)TUScope->getEntity())->addDecl(Alloc); } +bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, + DeclarationName Name, + FunctionDecl* &Operator) { + LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName); + // Try to find operator delete/operator delete[] in class scope. + LookupQualifiedName(Found, RD); + + if (Found.isAmbiguous()) + return true; + + for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); + F != FEnd; ++F) { + if (CXXMethodDecl *Delete = dyn_cast<CXXMethodDecl>(*F)) + if (Delete->isUsualDeallocationFunction()) { + Operator = Delete; + return false; + } + } + + // We did find operator delete/operator delete[] declarations, but + // none of them were suitable. + if (!Found.empty()) { + Diag(StartLoc, diag::err_no_suitable_delete_member_function_found) + << Name << RD; + + for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); + F != FEnd; ++F) { + Diag((*F)->getLocation(), + diag::note_delete_member_function_declared_here) + << Name; + } + + return true; + } + + // Look for a global declaration. + DeclareGlobalNewDelete(); + DeclContext *TUDecl = Context.getTranslationUnitDecl(); + + CXXNullPtrLiteralExpr Null(Context.VoidPtrTy, SourceLocation()); + Expr* DeallocArgs[1]; + DeallocArgs[0] = &Null; + if (FindAllocationOverload(StartLoc, SourceRange(), Name, + DeallocArgs, 1, TUDecl, /*AllowMissing=*/false, + Operator)) + return true; + + assert(Operator && "Did not find a deallocation function!"); + return false; +} + /// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in: /// @code ::delete ptr; @endcode /// or @@ -845,32 +896,21 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName( ArrayForm ? OO_Array_Delete : OO_Delete); - if (Pointee->isRecordType() && !UseGlobal) { - CXXRecordDecl *Record - = cast<CXXRecordDecl>(Pointee->getAs<RecordType>()->getDecl()); - - // Try to find operator delete/operator delete[] in class scope. - LookupResult Found; - LookupQualifiedName(Found, Record, DeleteName, LookupOrdinaryName); - // FIXME: Diagnose ambiguity properly - assert(!Found.isAmbiguous() && "Ambiguous delete/delete[] not handled"); - for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); - F != FEnd; ++F) { - if (CXXMethodDecl *Delete = dyn_cast<CXXMethodDecl>(*F)) - if (Delete->isUsualDeallocationFunction()) { - OperatorDelete = Delete; - break; - } - } + if (const RecordType *RT = Pointee->getAs<RecordType>()) { + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + + if (!UseGlobal && + FindDeallocationFunction(StartLoc, RD, DeleteName, OperatorDelete)) + return ExprError(); - if (!Record->hasTrivialDestructor()) - if (const CXXDestructorDecl *Dtor = Record->getDestructor(Context)) + if (!RD->hasTrivialDestructor()) + if (const CXXDestructorDecl *Dtor = RD->getDestructor(Context)) MarkDeclarationReferenced(StartLoc, const_cast<CXXDestructorDecl*>(Dtor)); } - + if (!OperatorDelete) { - // Didn't find a member overload. Look for a global one. + // Look for a global declaration. DeclareGlobalNewDelete(); DeclContext *TUDecl = Context.getTranslationUnitDecl(); if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName, @@ -1064,10 +1104,11 @@ Sema::BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind, bool Sema::PerformImplicitConversion(Expr *&From, QualType ToType, const ImplicitConversionSequence &ICS, - const char* Flavor) { + const char* Flavor, bool IgnoreBaseAccess) { switch (ICS.ConversionKind) { case ImplicitConversionSequence::StandardConversion: - if (PerformImplicitConversion(From, ToType, ICS.Standard, Flavor)) + if (PerformImplicitConversion(From, ToType, ICS.Standard, Flavor, + IgnoreBaseAccess)) return true; break; @@ -1086,18 +1127,22 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, } else if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(FD)) { CastKind = CastExpr::CK_ConstructorConversion; - - // 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(); + // Do no conversion if dealing with ... for the first conversion. + 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(); } else assert(0 && "Unknown conversion function kind!"); - - if (PerformImplicitConversion(From, BeforeToType, - ICS.UserDefined.Before, "converting")) - return true; + // Whatch out for elipsis conversion. + if (!ICS.UserDefined.EllipsisConversion) { + if (PerformImplicitConversion(From, BeforeToType, + ICS.UserDefined.Before, "converting", + IgnoreBaseAccess)) + return true; + } OwningExprResult CastArg = BuildCXXCastArgument(From->getLocStart(), @@ -1145,7 +1190,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, bool Sema::PerformImplicitConversion(Expr *&From, QualType ToType, const StandardConversionSequence& SCS, - const char *Flavor) { + const char *Flavor, bool IgnoreBaseAccess) { // Overall FIXME: we are recomputing too many types here and doing far too // much extra work. What this means is that we need to keep track of more // information that is computed when we try the implicit conversion initially, @@ -1273,7 +1318,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, CastExpr::CastKind Kind = CastExpr::CK_Unknown; - if (CheckPointerConversion(From, ToType, Kind)) + if (CheckPointerConversion(From, ToType, Kind, IgnoreBaseAccess)) return true; ImpCastExprToType(From, ToType, Kind); break; @@ -1281,7 +1326,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, case ICK_Pointer_Member: { CastExpr::CastKind Kind = CastExpr::CK_Unknown; - if (CheckMemberPointerConversion(From, ToType, Kind)) + if (CheckMemberPointerConversion(From, ToType, Kind, IgnoreBaseAccess)) return true; if (CheckExceptionSpecCompatibility(From, ToType)) return true; @@ -1292,6 +1337,17 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, ImpCastExprToType(From, Context.BoolTy, CastExpr::CK_Unknown); break; + case ICK_Derived_To_Base: + if (CheckDerivedToBaseConversion(From->getType(), + ToType.getNonReferenceType(), + From->getLocStart(), + From->getSourceRange(), + IgnoreBaseAccess)) + return true; + ImpCastExprToType(From, ToType.getNonReferenceType(), + CastExpr::CK_DerivedToBase); + break; + default: assert(false && "Improper second standard conversion"); break; @@ -1309,7 +1365,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, CastExpr::CK_NoOp, ToType->isLValueReferenceType()); break; - + default: assert(false && "Improper second standard conversion"); break; @@ -1374,8 +1430,7 @@ QualType Sema::CheckPointerToMemberOperands( } } - if (Context.getCanonicalType(Class).getUnqualifiedType() != - Context.getCanonicalType(LType).getUnqualifiedType()) { + if (!Context.hasSameUnqualifiedType(Class, LType)) { CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false, /*DetectVirtual=*/false); // FIXME: Would it be useful to print full ambiguity paths, or is that @@ -1827,8 +1882,6 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) { !T2->isPointerType() && !T2->isMemberPointerType()) return QualType(); - // FIXME: Do we need to work on the canonical types? - // C++0x 5.9p2 // Pointer conversions and qualification conversions are performed on // pointer operands to bring them to their composite pointer type. If @@ -1850,8 +1903,8 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) { } // Now both have to be pointers or member pointers. - if (!T1->isPointerType() && !T1->isMemberPointerType() && - !T2->isPointerType() && !T2->isMemberPointerType()) + if ((!T1->isPointerType() && !T1->isMemberPointerType()) || + (!T2->isPointerType() && !T2->isMemberPointerType())) return QualType(); // Otherwise, of one of the operands has type "pointer to cv1 void," then @@ -1865,9 +1918,13 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) { // conversions in both directions. If only one works, or if the two composite // types are the same, we have succeeded. // FIXME: extended qualifiers? - llvm::SmallVector<unsigned, 4> QualifierUnion; - llvm::SmallVector<std::pair<const Type *, const Type *>, 4> MemberOfClass; - QualType Composite1 = T1, Composite2 = T2; + typedef llvm::SmallVector<unsigned, 4> QualifierVector; + QualifierVector QualifierUnion; + typedef llvm::SmallVector<std::pair<const Type *, const Type *>, 4> + ContainingClassVector; + ContainingClassVector MemberOfClass; + QualType Composite1 = Context.getCanonicalType(T1), + Composite2 = Context.getCanonicalType(T2); do { const PointerType *Ptr1, *Ptr2; if ((Ptr1 = Composite1->getAs<PointerType>()) && @@ -1899,11 +1956,11 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) { } while (true); // Rewrap the composites as pointers or member pointers with the union CVRs. - llvm::SmallVector<std::pair<const Type *, const Type *>, 4>::iterator MOC - = MemberOfClass.begin(); - for (llvm::SmallVector<unsigned, 4>::iterator - I = QualifierUnion.begin(), - E = QualifierUnion.end(); + ContainingClassVector::reverse_iterator MOC + = MemberOfClass.rbegin(); + for (QualifierVector::reverse_iterator + I = QualifierUnion.rbegin(), + E = QualifierUnion.rend(); I != E; (void)++I, ++MOC) { Qualifiers Quals = Qualifiers::fromCVRMask(*I); if (MOC->first && MOC->second) { @@ -2085,12 +2142,19 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc, return move(Base); } + // The object type must be complete (or dependent). + if (!BaseType->isDependentType() && + RequireCompleteType(OpLoc, BaseType, + PDiag(diag::err_incomplete_member_access))) + return ExprError(); + // C++ [basic.lookup.classref]p2: // If the id-expression in a class member access (5.2.5) is an - // unqualified-id, and the type of the object expres- sion is of a class + // unqualified-id, and the type of the object expression is of a class // type C (or of pointer to a class type C), the unqualified-id is looked // up in the scope of class C. [...] ObjectType = BaseType.getAsOpaquePtr(); + return move(Base); } @@ -2108,7 +2172,7 @@ CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, CXXMemberCallExpr *CE = new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, - SourceLocation()); + Exp->getLocEnd()); return CE; } diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 4746a25..0f973d6d 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -174,7 +174,8 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType, // copy-initialization where the cv-unqualified version of the // source type is the same class as, or a derived class of, the // class of the destination, constructors are considered. - if ((DeclTypeC.getUnqualifiedType() == InitTypeC.getUnqualifiedType()) || + if ((DeclTypeC.getLocalUnqualifiedType() + == InitTypeC.getLocalUnqualifiedType()) || IsDerivedFrom(InitTypeC, DeclTypeC)) { const CXXRecordDecl *RD = cast<CXXRecordDecl>(DeclType->getAs<RecordType>()->getDecl()); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 93752e1..1f49b78 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// #include "Sema.h" +#include "Lookup.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" @@ -34,77 +35,161 @@ using namespace clang; -typedef llvm::SmallVector<UsingDirectiveDecl*, 4> UsingDirectivesTy; -typedef llvm::DenseSet<NamespaceDecl*> NamespaceSet; +namespace { + class UnqualUsingEntry { + const DeclContext *Nominated; + const DeclContext *CommonAncestor; -/// UsingDirAncestorCompare - Implements strict weak ordering of -/// UsingDirectives. It orders them by address of its common ancestor. -struct UsingDirAncestorCompare { + public: + UnqualUsingEntry(const DeclContext *Nominated, + const DeclContext *CommonAncestor) + : Nominated(Nominated), CommonAncestor(CommonAncestor) { + } - /// @brief Compares UsingDirectiveDecl common ancestor with DeclContext. - bool operator () (UsingDirectiveDecl *U, const DeclContext *Ctx) const { - return U->getCommonAncestor() < Ctx; - } + const DeclContext *getCommonAncestor() const { + return CommonAncestor; + } - /// @brief Compares UsingDirectiveDecl common ancestor with DeclContext. - bool operator () (const DeclContext *Ctx, UsingDirectiveDecl *U) const { - return Ctx < U->getCommonAncestor(); - } + const DeclContext *getNominatedNamespace() const { + return Nominated; + } - /// @brief Compares UsingDirectiveDecl common ancestors. - bool operator () (UsingDirectiveDecl *U1, UsingDirectiveDecl *U2) const { - return U1->getCommonAncestor() < U2->getCommonAncestor(); - } -}; - -/// AddNamespaceUsingDirectives - Adds all UsingDirectiveDecl's to heap UDirs -/// (ordered by common ancestors), found in namespace NS, -/// including all found (recursively) in their nominated namespaces. -void AddNamespaceUsingDirectives(ASTContext &Context, - DeclContext *NS, - UsingDirectivesTy &UDirs, - NamespaceSet &Visited) { - DeclContext::udir_iterator I, End; - - for (llvm::tie(I, End) = NS->getUsingDirectives(); I !=End; ++I) { - UDirs.push_back(*I); - std::push_heap(UDirs.begin(), UDirs.end(), UsingDirAncestorCompare()); - NamespaceDecl *Nominated = (*I)->getNominatedNamespace(); - if (Visited.insert(Nominated).second) - AddNamespaceUsingDirectives(Context, Nominated, UDirs, /*ref*/ Visited); - } -} + // Sort by the pointer value of the common ancestor. + struct Comparator { + bool operator()(const UnqualUsingEntry &L, const UnqualUsingEntry &R) { + return L.getCommonAncestor() < R.getCommonAncestor(); + } -/// AddScopeUsingDirectives - Adds all UsingDirectiveDecl's found in Scope S, -/// including all found in the namespaces they nominate. -static void AddScopeUsingDirectives(ASTContext &Context, Scope *S, - UsingDirectivesTy &UDirs) { - NamespaceSet VisitedNS; + bool operator()(const UnqualUsingEntry &E, const DeclContext *DC) { + return E.getCommonAncestor() < DC; + } - if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) { + bool operator()(const DeclContext *DC, const UnqualUsingEntry &E) { + return DC < E.getCommonAncestor(); + } + }; + }; + + /// A collection of using directives, as used by C++ unqualified + /// lookup. + class UnqualUsingDirectiveSet { + typedef llvm::SmallVector<UnqualUsingEntry, 8> ListTy; + + ListTy list; + llvm::SmallPtrSet<DeclContext*, 8> visited; + + public: + UnqualUsingDirectiveSet() {} + + void visitScopeChain(Scope *S, Scope *InnermostFileScope) { + // C++ [namespace.udir]p1: + // During unqualified name lookup, the names appear as if they + // were declared in the nearest enclosing namespace which contains + // both the using-directive and the nominated namespace. + DeclContext *InnermostFileDC + = static_cast<DeclContext*>(InnermostFileScope->getEntity()); + assert(InnermostFileDC && InnermostFileDC->isFileContext()); + + for (; S; S = S->getParent()) { + if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) { + DeclContext *EffectiveDC = (Ctx->isFileContext() ? Ctx : InnermostFileDC); + visit(Ctx, EffectiveDC); + } else { + Scope::udir_iterator I = S->using_directives_begin(), + End = S->using_directives_end(); + + for (; I != End; ++I) + visit(I->getAs<UsingDirectiveDecl>(), InnermostFileDC); + } + } + } - if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(Ctx)) - VisitedNS.insert(NS); + // Visits a context and collect all of its using directives + // recursively. Treats all using directives as if they were + // declared in the context. + // + // A given context is only every visited once, so it is important + // that contexts be visited from the inside out in order to get + // the effective DCs right. + void visit(DeclContext *DC, DeclContext *EffectiveDC) { + if (!visited.insert(DC)) + return; + + addUsingDirectives(DC, EffectiveDC); + } - AddNamespaceUsingDirectives(Context, Ctx, UDirs, /*ref*/ VisitedNS); + // Visits a using directive and collects all of its using + // directives recursively. Treats all using directives as if they + // were declared in the effective DC. + void visit(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) { + DeclContext *NS = UD->getNominatedNamespace(); + if (!visited.insert(NS)) + return; - } else { - Scope::udir_iterator I = S->using_directives_begin(), - End = S->using_directives_end(); - - for (; I != End; ++I) { - UsingDirectiveDecl *UD = I->getAs<UsingDirectiveDecl>(); - UDirs.push_back(UD); - std::push_heap(UDirs.begin(), UDirs.end(), UsingDirAncestorCompare()); - - NamespaceDecl *Nominated = UD->getNominatedNamespace(); - if (!VisitedNS.count(Nominated)) { - VisitedNS.insert(Nominated); - AddNamespaceUsingDirectives(Context, Nominated, UDirs, - /*ref*/ VisitedNS); + addUsingDirective(UD, EffectiveDC); + addUsingDirectives(NS, EffectiveDC); + } + + // Adds all the using directives in a context (and those nominated + // by its using directives, transitively) as if they appeared in + // the given effective context. + void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) { + llvm::SmallVector<DeclContext*,4> queue; + while (true) { + DeclContext::udir_iterator I, End; + for (llvm::tie(I, End) = DC->getUsingDirectives(); I != End; ++I) { + UsingDirectiveDecl *UD = *I; + DeclContext *NS = UD->getNominatedNamespace(); + if (visited.insert(NS)) { + addUsingDirective(UD, EffectiveDC); + queue.push_back(NS); + } + } + + if (queue.empty()) + return; + + DC = queue.back(); + queue.pop_back(); } } - } + + // Add a using directive as if it had been declared in the given + // context. This helps implement C++ [namespace.udir]p3: + // The using-directive is transitive: if a scope contains a + // using-directive that nominates a second namespace that itself + // contains using-directives, the effect is as if the + // using-directives from the second namespace also appeared in + // the first. + void addUsingDirective(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) { + // Find the common ancestor between the effective context and + // the nominated namespace. + DeclContext *Common = UD->getNominatedNamespace(); + while (!Common->Encloses(EffectiveDC)) + Common = Common->getParent(); + Common = Common->getPrimaryContext(); + + list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common)); + } + + void done() { + std::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator()); + } + + typedef ListTy::iterator iterator; + typedef ListTy::const_iterator const_iterator; + + iterator begin() { return list.begin(); } + iterator end() { return list.end(); } + const_iterator begin() const { return list.begin(); } + const_iterator end() const { return list.end(); } + + std::pair<const_iterator,const_iterator> + getNamespacesFor(DeclContext *DC) const { + return std::equal_range(begin(), end(), DC->getPrimaryContext(), + UnqualUsingEntry::Comparator()); + } + }; } // Retrieve the set of identifier namespaces that correspond to a @@ -153,42 +238,50 @@ getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind, } // Necessary because CXXBasePaths is not complete in Sema.h -void Sema::LookupResult::deletePaths(CXXBasePaths *Paths) { +void LookupResult::deletePaths(CXXBasePaths *Paths) { delete Paths; } -void Sema::LookupResult::resolveKind() { +void LookupResult::resolveKind() { unsigned N = Decls.size(); // Fast case: no possible ambiguity. - if (N <= 1) return; + if (N == 0) return; + if (N == 1) { + if (isa<UnresolvedUsingValueDecl>(Decls[0])) + ResultKind = FoundUnresolvedValue; + return; + } // Don't do any extra resolution if we've already resolved as ambiguous. - if (Kind == Ambiguous) return; + if (ResultKind == Ambiguous) return; llvm::SmallPtrSet<NamedDecl*, 16> Unique; bool Ambiguous = false; bool HasTag = false, HasFunction = false, HasNonFunction = false; + bool HasUnresolved = false; unsigned UniqueTagIndex = 0; unsigned I = 0; while (I < N) { - NamedDecl *D = Decls[I]; - assert(D == D->getUnderlyingDecl()); + NamedDecl *D = Decls[I]->getUnderlyingDecl(); + D = cast<NamedDecl>(D->getCanonicalDecl()); - NamedDecl *CanonD = cast<NamedDecl>(D->getCanonicalDecl()); - if (!Unique.insert(CanonD)) { + if (!Unique.insert(D)) { // If it's not unique, pull something off the back (and // continue at this index). Decls[I] = Decls[--N]; - } else if (isa<UnresolvedUsingDecl>(D)) { - // FIXME: proper support for UnresolvedUsingDecls. + } else if (isa<UnresolvedUsingValueDecl>(D)) { + // FIXME: support unresolved using value declarations Decls[I] = Decls[--N]; } else { // Otherwise, do some decl type analysis and then continue. - if (isa<TagDecl>(D)) { + + if (isa<UnresolvedUsingValueDecl>(D)) { + HasUnresolved = true; + } else if (isa<TagDecl>(D)) { if (HasTag) Ambiguous = true; UniqueTagIndex = I; @@ -213,7 +306,8 @@ void Sema::LookupResult::resolveKind() { // wherever the object, function, or enumerator name is visible. // But it's still an error if there are distinct tag types found, // even if they're not visible. (ref?) - if (HasTag && !Ambiguous && (HasFunction || HasNonFunction)) + if (HideTags && HasTag && !Ambiguous && !HasUnresolved && + (HasFunction || HasNonFunction)) Decls[UniqueTagIndex] = Decls[--N]; Decls.set_size(N); @@ -223,10 +317,12 @@ void Sema::LookupResult::resolveKind() { if (Ambiguous) setAmbiguous(LookupResult::AmbiguousReference); + else if (HasUnresolved) + ResultKind = LookupResult::FoundUnresolvedValue; else if (N > 1) - Kind = LookupResult::FoundOverloaded; + ResultKind = LookupResult::FoundOverloaded; else - Kind = LookupResult::Found; + ResultKind = LookupResult::Found; } /// @brief Converts the result of name lookup into a single (possible @@ -242,10 +338,10 @@ void Sema::LookupResult::resolveKind() { /// solution, since it causes the OverloadedFunctionDecl to be /// leaked. FIXME: Eventually, there will be a better way to iterate /// over the set of overloaded functions returned by name lookup. -NamedDecl *Sema::LookupResult::getAsSingleDecl(ASTContext &C) const { +NamedDecl *LookupResult::getAsSingleDecl(ASTContext &C) const { size_t size = Decls.size(); if (size == 0) return 0; - if (size == 1) return *begin(); + if (size == 1) return (*begin())->getUnderlyingDecl(); if (isAmbiguous()) return 0; @@ -255,9 +351,7 @@ NamedDecl *Sema::LookupResult::getAsSingleDecl(ASTContext &C) const { = OverloadedFunctionDecl::Create(C, (*I)->getDeclContext(), (*I)->getDeclName()); for (; I != E; ++I) { - NamedDecl *ND = *I; - assert(ND->getUnderlyingDecl() == ND - && "decls in lookup result should have redirections stripped"); + NamedDecl *ND = (*I)->getUnderlyingDecl(); assert(ND->isFunctionOrFunctionTemplate()); if (isa<FunctionDecl>(ND)) Ovl->addOverload(cast<FunctionDecl>(ND)); @@ -269,7 +363,7 @@ NamedDecl *Sema::LookupResult::getAsSingleDecl(ASTContext &C) const { return Ovl; } -void Sema::LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) { +void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) { CXXBasePaths::paths_iterator I, E; DeclContext::lookup_iterator DI, DE; for (I = P.begin(), E = P.end(); I != E; ++I) @@ -277,7 +371,7 @@ void Sema::LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) { addDecl(*DI); } -void Sema::LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) { +void LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) { Paths = new CXXBasePaths; Paths->swap(P); addDeclsFromBasePaths(*Paths); @@ -285,7 +379,7 @@ void Sema::LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) { setAmbiguous(AmbiguousBaseSubobjects); } -void Sema::LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) { +void LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) { Paths = new CXXBasePaths; Paths->swap(P); addDeclsFromBasePaths(*Paths); @@ -293,7 +387,7 @@ void Sema::LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) { setAmbiguous(AmbiguousBaseSubobjectTypes); } -void Sema::LookupResult::print(llvm::raw_ostream &Out) { +void LookupResult::print(llvm::raw_ostream &Out) { Out << Decls.size() << " result(s)"; if (isAmbiguous()) Out << ", ambiguous"; if (Paths) Out << ", base paths present"; @@ -306,42 +400,36 @@ void Sema::LookupResult::print(llvm::raw_ostream &Out) { // Adds all qualifying matches for a name within a decl context to the // given lookup result. Returns true if any matches were found. -static bool LookupDirect(Sema::LookupResult &R, DeclContext *DC, - DeclarationName Name, - Sema::LookupNameKind NameKind, - unsigned IDNS) { +static bool LookupDirect(LookupResult &R, const DeclContext *DC) { bool Found = false; - DeclContext::lookup_iterator I, E; - for (llvm::tie(I, E) = DC->lookup(Name); I != E; ++I) - if (Sema::isAcceptableLookupResult(*I, NameKind, IDNS)) + DeclContext::lookup_const_iterator I, E; + for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) + if (Sema::isAcceptableLookupResult(*I, R.getLookupKind(), + R.getIdentifierNamespace())) R.addDecl(*I), Found = true; return Found; } +// Performs C++ unqualified lookup into the given file context. static bool -CppNamespaceLookup(Sema::LookupResult &R, ASTContext &Context, DeclContext *NS, - DeclarationName Name, Sema::LookupNameKind NameKind, - unsigned IDNS, UsingDirectivesTy *UDirs = 0) { +CppNamespaceLookup(LookupResult &R, ASTContext &Context, DeclContext *NS, + UnqualUsingDirectiveSet &UDirs) { assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!"); - // Perform qualified name lookup into the LookupCtx. - bool Found = LookupDirect(R, NS, Name, NameKind, IDNS); - - if (UDirs) { - // For each UsingDirectiveDecl, which common ancestor is equal - // to NS, we preform qualified name lookup into namespace nominated by it. - UsingDirectivesTy::const_iterator UI, UEnd; - llvm::tie(UI, UEnd) = - std::equal_range(UDirs->begin(), UDirs->end(), NS, - UsingDirAncestorCompare()); - - for (; UI != UEnd; ++UI) - if (LookupDirect(R, (*UI)->getNominatedNamespace(), Name, NameKind, IDNS)) - Found = true; - } + // Perform direct name lookup into the LookupCtx. + bool Found = LookupDirect(R, NS); + + // Perform direct name lookup into the namespaces nominated by the + // using directives whose common ancestor is this namespace. + UnqualUsingDirectiveSet::const_iterator UI, UEnd; + llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS); + + for (; UI != UEnd; ++UI) + if (LookupDirect(R, UI->getNominatedNamespace())) + Found = true; R.resolveKind(); @@ -363,20 +451,23 @@ static DeclContext *findOuterContext(Scope *S) { return 0; } -bool -Sema::CppLookupName(LookupResult &R, Scope *S, DeclarationName Name, - LookupNameKind NameKind, bool RedeclarationOnly) { +bool Sema::CppLookupName(LookupResult &R, Scope *S) { assert(getLangOptions().CPlusPlus && "Can perform only C++ lookup"); + LookupNameKind NameKind = R.getLookupKind(); unsigned IDNS = getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true); // If we're testing for redeclarations, also look in the friend namespaces. - if (RedeclarationOnly) { + if (R.isForRedeclaration()) { if (IDNS & Decl::IDNS_Tag) IDNS |= Decl::IDNS_TagFriend; if (IDNS & Decl::IDNS_Ordinary) IDNS |= Decl::IDNS_OrdinaryFriend; } + R.setIdentifierNamespace(IDNS); + + DeclarationName Name = R.getLookupName(); + Scope *Initial = S; IdentifierResolver::iterator I = IdResolver.begin(Name), @@ -427,24 +518,25 @@ Sema::CppLookupName(LookupResult &R, Scope *S, DeclarationName Name, // example, inside a class without any base classes, we never need to // perform qualified lookup because all of the members are on top of the // identifier chain. - if (LookupQualifiedName(R, Ctx, Name, NameKind, RedeclarationOnly)) + if (LookupQualifiedName(R, Ctx)) return true; } } } + // Stop if we ran out of scopes. + // FIXME: This really, really shouldn't be happening. + if (!S) return false; + // Collect UsingDirectiveDecls in all scopes, and recursively all // nominated namespaces by those using-directives. - // UsingDirectives are pushed to heap, in common ancestor pointer value order. + // // FIXME: Cache this sorted list in Scope structure, and DeclContext, so we // don't build it for each lookup! - UsingDirectivesTy UDirs; - for (Scope *SC = Initial; SC; SC = SC->getParent()) - if (SC->getFlags() & Scope::DeclScope) - AddScopeUsingDirectives(Context, SC, UDirs); - // Sort heapified UsingDirectiveDecls. - std::sort_heap(UDirs.begin(), UDirs.end(), UsingDirAncestorCompare()); + UnqualUsingDirectiveSet UDirs; + UDirs.visitScopeChain(Initial, S); + UDirs.done(); // Lookup namespace scope, and global scope. // Unqualified name lookup in C++ requires looking into scopes @@ -473,7 +565,7 @@ Sema::CppLookupName(LookupResult &R, Scope *S, DeclarationName Name, } // Look into context considering using-directives. - if (CppNamespaceLookup(R, Context, Ctx, Name, NameKind, IDNS, &UDirs)) + if (CppNamespaceLookup(R, Context, Ctx, UDirs)) Found = true; if (Found) { @@ -481,7 +573,7 @@ Sema::CppLookupName(LookupResult &R, Scope *S, DeclarationName Name, return true; } - if (RedeclarationOnly && !Ctx->isTransparentContext()) + if (R.isForRedeclaration() && !Ctx->isTransparentContext()) return false; } @@ -519,11 +611,12 @@ Sema::CppLookupName(LookupResult &R, Scope *S, DeclarationName Name, /// @returns The result of name lookup, which includes zero or more /// declarations and possibly additional information used to diagnose /// ambiguities. -bool Sema::LookupName(LookupResult &R, Scope *S, DeclarationName Name, - LookupNameKind NameKind, bool RedeclarationOnly, - bool AllowBuiltinCreation, SourceLocation Loc) { +bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { + DeclarationName Name = R.getLookupName(); if (!Name) return false; + LookupNameKind NameKind = R.getLookupKind(); + if (!getLangOptions().CPlusPlus) { // Unqualified name lookup in C/Objective-C is purely lexical, so // search in the declarations attached to the name. @@ -619,7 +712,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, DeclarationName Name, } } else { // Perform C++ unqualified name lookup. - if (CppLookupName(R, S, Name, NameKind, RedeclarationOnly)) + if (CppLookupName(R, S)) return true; } @@ -639,7 +732,8 @@ bool Sema::LookupName(LookupResult &R, Scope *S, DeclarationName Name, return false; NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, - S, RedeclarationOnly, Loc); + S, R.isForRedeclaration(), + R.getNameLoc()); if (D) R.addDecl(D); return (D != NULL); } @@ -674,11 +768,8 @@ bool Sema::LookupName(LookupResult &R, Scope *S, DeclarationName Name, /// class or enumeration name if and only if the declarations are /// from the same namespace; otherwise (the declarations are from /// different namespaces), the program is ill-formed. -static bool LookupQualifiedNameInUsingDirectives(Sema::LookupResult &R, - DeclContext *StartDC, - DeclarationName Name, - Sema::LookupNameKind NameKind, - unsigned IDNS) { +static bool LookupQualifiedNameInUsingDirectives(LookupResult &R, + DeclContext *StartDC) { assert(StartDC->isFileContext() && "start context is not a file context"); DeclContext::udir_iterator I = StartDC->using_directives_begin(); @@ -697,7 +788,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema::LookupResult &R, // We have already looked into the initial namespace; seed the queue // with its using-children. for (; I != E; ++I) { - NamespaceDecl *ND = (*I)->getNominatedNamespace(); + NamespaceDecl *ND = (*I)->getNominatedNamespace()->getOriginalNamespace(); if (Visited.insert(ND).second) Queue.push_back(ND); } @@ -709,7 +800,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema::LookupResult &R, bool FoundTag = false; bool FoundNonTag = false; - Sema::LookupResult LocalR; + LookupResult LocalR(LookupResult::Temporary, R); bool Found = false; while (!Queue.empty()) { @@ -719,8 +810,8 @@ static bool LookupQualifiedNameInUsingDirectives(Sema::LookupResult &R, // We go through some convolutions here to avoid copying results // between LookupResults. bool UseLocal = !R.empty(); - Sema::LookupResult &DirectR = UseLocal ? LocalR : R; - bool FoundDirect = LookupDirect(DirectR, ND, Name, NameKind, IDNS); + LookupResult &DirectR = UseLocal ? LocalR : R; + bool FoundDirect = LookupDirect(DirectR, ND); if (FoundDirect) { // First do any local hiding. @@ -792,22 +883,23 @@ static bool LookupQualifiedNameInUsingDirectives(Sema::LookupResult &R, /// @returns The result of name lookup, which includes zero or more /// declarations and possibly additional information used to diagnose /// ambiguities. -bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, - DeclarationName Name, LookupNameKind NameKind, - bool RedeclarationOnly) { +bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx) { assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context"); - if (!Name) + if (!R.getLookupName()) return false; // If we're performing qualified name lookup (e.g., lookup into a // struct), find fields as part of ordinary name lookup. + LookupNameKind NameKind = R.getLookupKind(); unsigned IDNS = getIdentifierNamespacesFromLookupNameKind(NameKind, getLangOptions().CPlusPlus); if (NameKind == LookupOrdinaryName) IDNS |= Decl::IDNS_Member; + R.setIdentifierNamespace(IDNS); + // Make sure that the declaration context is complete. assert((!isa<TagDecl>(LookupCtx) || LookupCtx->isDependentContext() || @@ -817,7 +909,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, "Declaration context must already be complete!"); // Perform qualified name lookup into the LookupCtx. - if (LookupDirect(R, LookupCtx, Name, NameKind, IDNS)) { + if (LookupDirect(R, LookupCtx)) { R.resolveKind(); return true; } @@ -831,13 +923,12 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // the unqualified-id shall name a member of the namespace // designated by the nested-name-specifier. // See also [class.mfct]p5 and [class.static.data]p2. - if (RedeclarationOnly) + if (R.isForRedeclaration()) return false; - // If this is a namespace, look it up in + // If this is a namespace, look it up in the implied namespaces. if (LookupCtx->isFileContext()) - return LookupQualifiedNameInUsingDirectives(R, LookupCtx, Name, NameKind, - IDNS); + return LookupQualifiedNameInUsingDirectives(R, LookupCtx); // If this isn't a C++ class, we aren't allowed to look into base // classes, we're done. @@ -851,7 +942,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // Look for this member in our base classes CXXRecordDecl::BaseMatchesCallback *BaseCallback = 0; - switch (NameKind) { + switch (R.getLookupKind()) { case LookupOrdinaryName: case LookupMemberName: case LookupRedeclarationWithLinkage: @@ -875,7 +966,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, break; } - if (!LookupRec->lookupInBases(BaseCallback, Name.getAsOpaquePtr(), Paths)) + if (!LookupRec->lookupInBases(BaseCallback, + R.getLookupName().getAsOpaquePtr(), Paths)) return false; // C++ [class.member.lookup]p2: @@ -977,10 +1069,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, /// /// @returns True if any decls were found (but possibly ambiguous) bool Sema::LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS, - DeclarationName Name, LookupNameKind NameKind, - bool RedeclarationOnly, bool AllowBuiltinCreation, - SourceLocation Loc, - bool EnteringContext) { + bool AllowBuiltinCreation, bool EnteringContext) { if (SS && SS->isInvalid()) { // When the scope specifier is invalid, don't even look for // anything. @@ -994,7 +1083,9 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS, if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS)) return false; - return LookupQualifiedName(R, DC, Name, NameKind, RedeclarationOnly); + R.setContextRange(SS->getRange()); + + return LookupQualifiedName(R, DC); } // We could not resolve the scope specified to a specific declaration @@ -1004,8 +1095,7 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS, } // Perform unqualified name lookup starting in the given scope. - return LookupName(R, S, Name, NameKind, RedeclarationOnly, - AllowBuiltinCreation, Loc); + return LookupName(R, S, AllowBuiltinCreation); } @@ -1025,11 +1115,13 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS, /// precedes the name. /// /// @returns true -bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name, - SourceLocation NameLoc, - SourceRange LookupRange) { +bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { assert(Result.isAmbiguous() && "Lookup result must be ambiguous"); + DeclarationName Name = Result.getLookupName(); + SourceLocation NameLoc = Result.getNameLoc(); + SourceRange LookupRange = Result.getContextRange(); + switch (Result.getAmbiguityKind()) { case LookupResult::AmbiguousBaseSubobjects: { CXXBasePaths *Paths = Result.getBasePaths(); @@ -1136,12 +1228,13 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg, AssociatedClasses); break; - case TemplateArgument::Declaration: + case TemplateArgument::Template: { // [...] the namespaces in which any template template arguments are // defined; and the classes in which any member templates used as // template template arguments are defined. + TemplateName Template = Arg.getAsTemplate(); if (ClassTemplateDecl *ClassTemplate - = dyn_cast<ClassTemplateDecl>(Arg.getAsDecl())) { + = dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) { DeclContext *Ctx = ClassTemplate->getDeclContext(); if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) AssociatedClasses.insert(EnclosingClass); @@ -1151,7 +1244,9 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg, CollectNamespace(AssociatedNamespaces, Ctx); } break; - + } + + case TemplateArgument::Declaration: case TemplateArgument::Integral: case TemplateArgument::Expression: // [Note: non-type template arguments do not contribute to the set of @@ -1490,8 +1585,7 @@ IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn, if (T1->isEnumeralType()) { QualType ArgType = Proto->getArgType(0).getNonReferenceType(); - if (Context.getCanonicalType(T1).getUnqualifiedType() - == Context.getCanonicalType(ArgType).getUnqualifiedType()) + if (Context.hasSameUnqualifiedType(T1, ArgType)) return true; } @@ -1500,14 +1594,21 @@ IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn, if (!T2.isNull() && T2->isEnumeralType()) { QualType ArgType = Proto->getArgType(1).getNonReferenceType(); - if (Context.getCanonicalType(T2).getUnqualifiedType() - == Context.getCanonicalType(ArgType).getUnqualifiedType()) + if (Context.hasSameUnqualifiedType(T2, ArgType)) return true; } return false; } +NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name, + LookupNameKind NameKind, + RedeclarationKind Redecl) { + LookupResult R(*this, Name, SourceLocation(), NameKind, Redecl); + LookupName(R, S); + return R.getAsSingleDecl(Context); +} + /// \brief Find the protocol with the given name, if any. ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II) { Decl *D = LookupSingleName(TUScope, II, LookupObjCProtocolName); @@ -1537,8 +1638,8 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, // of type T2 or "reference to (possibly cv-qualified) T2", // when T2 is an enumeration type, are candidate functions. DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); - LookupResult Operators; - LookupName(Operators, S, OpName, LookupOperatorName); + LookupResult Operators(*this, OpName, SourceLocation(), LookupOperatorName); + LookupName(Operators, S); assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous"); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 3e6778b..adcd977 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "Lookup.h" #include "clang/Basic/Diagnostic.h" #include "clang/Lex/Preprocessor.h" #include "clang/AST/ASTContext.h" @@ -350,7 +351,7 @@ Sema::IsOverload(FunctionDecl *New, Decl* OldD, if (NewTemplate && (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), OldTemplate->getTemplateParameters(), - false, false, SourceLocation()) || + false, TPL_TemplateMatch) || OldType->getResultType() != NewType->getResultType())) return true; @@ -519,8 +520,6 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // cv-unqualified version of T. Otherwise, the type of the rvalue // is T (C++ 4.1p1). C++ can't get here with class types; in C, we // just strip the qualifiers because they don't matter. - - // FIXME: Doesn't see through to qualifiers behind a typedef! FromType = FromType.getUnqualifiedType(); } else if (FromType->isArrayType()) { // Array-to-pointer conversion (C++ 4.2) @@ -678,8 +677,9 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // a conversion. [...] CanonFrom = Context.getCanonicalType(FromType); CanonTo = Context.getCanonicalType(ToType); - if (CanonFrom.getUnqualifiedType() == CanonTo.getUnqualifiedType() && - CanonFrom.getCVRQualifiers() != CanonTo.getCVRQualifiers()) { + if (CanonFrom.getLocalUnqualifiedType() + == CanonTo.getLocalUnqualifiedType() && + CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers()) { FromType = ToType; CanonFrom = CanonTo; } @@ -756,8 +756,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // We found the type that we can promote to. If this is the // type we wanted, we have a promotion. Otherwise, no // promotion. - return Context.getCanonicalType(ToType).getUnqualifiedType() - == Context.getCanonicalType(PromoteTypes[Idx]).getUnqualifiedType(); + return Context.hasSameUnqualifiedType(ToType, PromoteTypes[Idx]); } } } @@ -864,7 +863,7 @@ BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr, Qualifiers Quals = CanonFromPointee.getQualifiers(); // Exact qualifier match -> return the pointer type we're converting to. - if (CanonToPointee.getQualifiers() == Quals) { + if (CanonToPointee.getLocalQualifiers() == Quals) { // ToType is exactly what we need. Return it. if (!ToType.isNull()) return ToType; @@ -876,7 +875,8 @@ BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr, // Just build a canonical type that has the right qualifiers. return Context.getPointerType( - Context.getQualifiedType(CanonToPointee.getUnqualifiedType(), Quals)); + Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(), + Quals)); } static bool isNullPointerConstantForConversion(Expr *Expr, @@ -1155,7 +1155,8 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, /// true. It returns true and produces a diagnostic if there was an /// error, or returns false otherwise. bool Sema::CheckPointerConversion(Expr *From, QualType ToType, - CastExpr::CastKind &Kind) { + CastExpr::CastKind &Kind, + bool IgnoreBaseAccess) { QualType FromType = From->getType(); if (const PointerType *FromPtrType = FromType->getAs<PointerType>()) @@ -1169,7 +1170,8 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, // ambiguous or inaccessible conversion. if (CheckDerivedToBaseConversion(FromPointeeType, ToPointeeType, From->getExprLoc(), - From->getSourceRange())) + From->getSourceRange(), + IgnoreBaseAccess)) return true; // The conversion was successful. @@ -1238,7 +1240,9 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, /// true and produces a diagnostic if there was an error, or returns false /// otherwise. bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, - CastExpr::CastKind &Kind) { + CastExpr::CastKind &Kind, + bool IgnoreBaseAccess) { + (void)IgnoreBaseAccess; QualType FromType = From->getType(); const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>(); if (!FromPtrType) { @@ -1344,8 +1348,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType) { // of types. If we unwrapped any pointers, and if FromType and // ToType have the same unqualified type (since we checked // qualifiers above), then this is a qualification conversion. - return UnwrappedAnyPointer && - FromType.getUnqualifiedType() == ToType.getUnqualifiedType(); + return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType); } /// \brief Given a function template or function, extract the function template @@ -1399,6 +1402,13 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion( // functions are all the converting constructors (12.3.1) of // that class. The argument list is the expression-list within // the parentheses of the initializer. + bool SuppressUserConversions = !UserCast; + if (Context.hasSameUnqualifiedType(ToType, From->getType()) || + IsDerivedFrom(From->getType(), ToType)) { + SuppressUserConversions = false; + AllowConversionFunctions = false; + } + DeclarationName ConstructorName = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(ToType).getUnqualifiedType()); @@ -1415,20 +1425,18 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion( = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl()); else Constructor = cast<CXXConstructorDecl>(*Con); - + if (!Constructor->isInvalidDecl() && Constructor->isConvertingConstructor(AllowExplicit)) { if (ConstructorTmpl) AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0, &From, - 1, CandidateSet, - /*SuppressUserConversions=*/!UserCast, - ForceRValue); + 1, CandidateSet, + SuppressUserConversions, ForceRValue); else // Allow one user-defined conversion when user specifies a // From->ToType conversion via an static cast (c-style, etc). AddOverloadCandidate(Constructor, &From, 1, CandidateSet, - /*SuppressUserConversions=*/!UserCast, - ForceRValue); + SuppressUserConversions, ForceRValue); } } } @@ -1481,9 +1489,14 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion( // sequence converts the source type to the type required by // the argument of the constructor. // - // FIXME: What about ellipsis conversions? QualType ThisType = Constructor->getThisType(Context); - User.Before = Best->Conversions[0].Standard; + if (Best->Conversions[0].ConversionKind == + ImplicitConversionSequence::EllipsisConversion) + User.EllipsisConversion = true; + else { + User.Before = Best->Conversions[0].Standard; + User.EllipsisConversion = false; + } User.ConversionFunction = Constructor; User.After.setAsIdentityConversion(); User.After.FromTypePtr @@ -1500,6 +1513,7 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion( // implicit object parameter of the conversion function. User.Before = Best->Conversions[0].Standard; User.ConversionFunction = Conversion; + User.EllipsisConversion = false; // C++ [over.ics.user]p2: // The second standard conversion sequence converts the @@ -1727,7 +1741,7 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr); T1 = Context.getCanonicalType(T1); T2 = Context.getCanonicalType(T2); - if (T1.getUnqualifiedType() == T2.getUnqualifiedType()) { + if (Context.hasSameUnqualifiedType(T1, T2)) { if (T2.isMoreQualifiedThan(T1)) return ImplicitConversionSequence::Better; else if (T1.isMoreQualifiedThan(T2)) @@ -1763,7 +1777,7 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1, // If the types are the same, we won't learn anything by unwrapped // them. - if (T1.getUnqualifiedType() == T2.getUnqualifiedType()) + if (Context.hasSameUnqualifiedType(T1, T2)) return ImplicitConversionSequence::Indistinguishable; ImplicitConversionSequence::CompareKind Result @@ -1803,7 +1817,7 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1, } // If the types after this point are equivalent, we're done. - if (T1.getUnqualifiedType() == T2.getUnqualifiedType()) + if (Context.hasSameUnqualifiedType(T1, T2)) break; } @@ -1918,8 +1932,8 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, // -- binding of an expression of type C to a reference of type // B& is better than binding an expression of type C to a // reference of type A&, - if (FromType1.getUnqualifiedType() == FromType2.getUnqualifiedType() && - ToType1.getUnqualifiedType() != ToType2.getUnqualifiedType()) { + if (Context.hasSameUnqualifiedType(FromType1, FromType2) && + !Context.hasSameUnqualifiedType(ToType1, ToType2)) { if (IsDerivedFrom(ToType1, ToType2)) return ImplicitConversionSequence::Better; else if (IsDerivedFrom(ToType2, ToType1)) @@ -1929,8 +1943,8 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, // -- binding of an expression of type B to a reference of type // A& is better than binding an expression of type C to a // reference of type A&, - if (FromType1.getUnqualifiedType() != FromType2.getUnqualifiedType() && - ToType1.getUnqualifiedType() == ToType2.getUnqualifiedType()) { + if (!Context.hasSameUnqualifiedType(FromType1, FromType2) && + Context.hasSameUnqualifiedType(ToType1, ToType2)) { if (IsDerivedFrom(FromType2, FromType1)) return ImplicitConversionSequence::Better; else if (IsDerivedFrom(FromType1, FromType2)) @@ -1977,8 +1991,8 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, if (SCS1.CopyConstructor && SCS2.CopyConstructor && SCS1.Second == ICK_Derived_To_Base) { // -- conversion of C to B is better than conversion of C to A, - if (FromType1.getUnqualifiedType() == FromType2.getUnqualifiedType() && - ToType1.getUnqualifiedType() != ToType2.getUnqualifiedType()) { + if (Context.hasSameUnqualifiedType(FromType1, FromType2) && + !Context.hasSameUnqualifiedType(ToType1, ToType2)) { if (IsDerivedFrom(ToType1, ToType2)) return ImplicitConversionSequence::Better; else if (IsDerivedFrom(ToType2, ToType1)) @@ -1986,8 +2000,8 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, } // -- conversion of B to A is better than conversion of C to A. - if (FromType1.getUnqualifiedType() != FromType2.getUnqualifiedType() && - ToType1.getUnqualifiedType() == ToType2.getUnqualifiedType()) { + if (!Context.hasSameUnqualifiedType(FromType1, FromType2) && + Context.hasSameUnqualifiedType(ToType1, ToType2)) { if (IsDerivedFrom(FromType2, FromType1)) return ImplicitConversionSequence::Better; else if (IsDerivedFrom(FromType1, FromType2)) @@ -2099,14 +2113,15 @@ Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) { // First check the qualifiers. We don't care about lvalue-vs-rvalue // with the implicit object parameter (C++ [over.match.funcs]p5). QualType FromTypeCanon = Context.getCanonicalType(FromType); - if (ImplicitParamType.getCVRQualifiers() != FromTypeCanon.getCVRQualifiers() && + if (ImplicitParamType.getCVRQualifiers() + != FromTypeCanon.getLocalCVRQualifiers() && !ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) return ICS; // Check that we have either the same type or a derived type. It // affects the conversion rank. QualType ClassTypeCanon = Context.getCanonicalType(ClassType); - if (ClassTypeCanon == FromTypeCanon.getUnqualifiedType()) + if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) ICS.Standard.Second = ICK_Identity; else if (IsDerivedFrom(FromType, ClassType)) ICS.Standard.Second = ICK_Derived_To_Base; @@ -2228,7 +2243,18 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, if (!CandidateSet.isNewCandidate(Function)) return; - + + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function)){ + // C++ [class.copy]p3: + // A member function template is never instantiated to perform the copy + // of a class object to an object of its class type. + QualType ClassType = Context.getTypeDeclType(Constructor->getParent()); + if (NumArgs == 1 && + Constructor->isCopyConstructorLikeSpecialization() && + Context.hasSameUnqualifiedType(ClassType, Args[0]->getType())) + return; + } + // Add this candidate CandidateSet.push_back(OverloadCandidate()); OverloadCandidate& Candidate = CandidateSet.back(); @@ -2342,6 +2368,33 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions, } } +/// AddMethodCandidate - Adds a named decl (which is some kind of +/// method) as a method candidate to the given overload set. +void Sema::AddMethodCandidate(NamedDecl *Decl, Expr *Object, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions, bool ForceRValue) { + + // FIXME: use this + //DeclContext *ActingContext = Decl->getDeclContext(); + + if (isa<UsingShadowDecl>(Decl)) + Decl = cast<UsingShadowDecl>(Decl)->getTargetDecl(); + + if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) { + assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) && + "Expected a member function template"); + AddMethodTemplateCandidate(TD, false, 0, 0, + Object, Args, NumArgs, + CandidateSet, + SuppressUserConversions, + ForceRValue); + } else { + AddMethodCandidate(cast<CXXMethodDecl>(Decl), Object, Args, NumArgs, + CandidateSet, SuppressUserConversions, ForceRValue); + } +} + /// AddMethodCandidate - Adds the given C++ member function to the set /// of candidate functions, using the given function call arguments /// and the object argument (@c Object). For example, in a call @@ -2593,7 +2646,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, // call on the stack and we don't need its arguments to be // well-formed. DeclRefExpr ConversionRef(Conversion, Conversion->getType(), - SourceLocation()); + From->getLocStart()); ImplicitCastExpr ConversionFn(Context.getPointerType(Conversion->getType()), CastExpr::CK_FunctionToPointerDecay, &ConversionRef, false); @@ -2603,7 +2656,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, // allocator). CallExpr Call(Context, &ConversionFn, 0, 0, Conversion->getConversionType().getNonReferenceType(), - SourceLocation()); + From->getLocStart()); ImplicitConversionSequence ICS = TryCopyInitialization(&Call, ToType, /*SuppressUserConversions=*/true, @@ -2693,6 +2746,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, Candidate.Conversions[0].ConversionKind = ImplicitConversionSequence::UserDefinedConversion; Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard; + Candidate.Conversions[0].UserDefined.EllipsisConversion = false; Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion; Candidate.Conversions[0].UserDefined.After = Candidate.Conversions[0].UserDefined.Before; @@ -2807,27 +2861,16 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, if (RequireCompleteType(OpLoc, T1, PDiag())) return; - LookupResult Operators; - LookupQualifiedName(Operators, T1Rec->getDecl(), OpName, - LookupOrdinaryName, false); + LookupResult Operators(*this, OpName, OpLoc, LookupOrdinaryName); + LookupQualifiedName(Operators, T1Rec->getDecl()); + Operators.suppressDiagnostics(); + for (LookupResult::iterator Oper = Operators.begin(), OperEnd = Operators.end(); Oper != OperEnd; - ++Oper) { - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Oper)) { - AddMethodCandidate(Method, Args[0], Args+1, NumArgs - 1, CandidateSet, - /*SuppressUserConversions=*/false); - continue; - } - - assert(isa<FunctionTemplateDecl>(*Oper) && - isa<CXXMethodDecl>(cast<FunctionTemplateDecl>(*Oper) - ->getTemplatedDecl()) && - "Expected a member function template"); - AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Oper), false, 0, 0, - Args[0], Args+1, NumArgs - 1, CandidateSet, - /*SuppressUserConversions=*/false); - } + ++Oper) + AddMethodCandidate(*Oper, Args[0], Args + 1, NumArgs - 1, CandidateSet, + /* SuppressUserConversions = */ false); } } @@ -2975,6 +3018,8 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty, QualType PointeeTy = PointerTy->getPointeeType(); unsigned BaseCVR = PointeeTy.getCVRQualifiers(); + if (const ConstantArrayType *Array =Context.getAsConstantArrayType(PointeeTy)) + BaseCVR = Array->getElementType().getCVRQualifiers(); bool hasVolatile = VisibleQuals.hasVolatile(); bool hasRestrict = VisibleQuals.hasRestrict(); @@ -3050,7 +3095,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, Ty = RefTy->getPointeeType(); // We don't care about qualifiers on the type. - Ty = Ty.getUnqualifiedType(); + Ty = Ty.getLocalUnqualifiedType(); // If we're dealing with an array type, decay to the pointer. if (Ty->isArrayType()) @@ -4710,10 +4755,10 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UsualUnaryConversions(FnExpr); input.release(); - + Args[0] = Input; ExprOwningPtr<CallExpr> TheCall(this, new (Context) CXXOperatorCallExpr(Context, Op, FnExpr, - &Input, 1, ResultTy, OpLoc)); + Args, NumArgs, ResultTy, OpLoc)); if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall.get(), FnDecl)) @@ -5226,17 +5271,22 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // (E).operator(). OverloadCandidateSet CandidateSet; DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call); - DeclContext::lookup_const_iterator Oper, OperEnd; - for (llvm::tie(Oper, OperEnd) = Record->getDecl()->lookup(OpName); - Oper != OperEnd; ++Oper) - AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Object, Args, NumArgs, - CandidateSet, /*SuppressUserConversions=*/false); if (RequireCompleteType(LParenLoc, Object->getType(), PartialDiagnostic(diag::err_incomplete_object_call) - << Object->getSourceRange())) + << Object->getSourceRange())) return true; + LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName); + LookupQualifiedName(R, Record->getDecl()); + R.suppressDiagnostics(); + + for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); + Oper != OperEnd; ++Oper) { + AddMethodCandidate(*Oper, Object, Args, NumArgs, CandidateSet, + /*SuppressUserConversions=*/ false); + } + // C++ [over.call.object]p2: // In addition, for each conversion function declared in T of the // form @@ -5405,7 +5455,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, QualType ProtoArgType = Proto->getArgType(i); IsError |= PerformCopyInitialization(Arg, ProtoArgType, "passing"); } else { - Arg = CXXDefaultArgExpr::Create(Context, Method->getParamDecl(i)); + OwningExprResult DefArg + = BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i)); + if (DefArg.isInvalid()) { + IsError = true; + break; + } + + Arg = DefArg.takeAs<Expr>(); } TheCall->setArg(i + 1, Arg); @@ -5447,8 +5504,14 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { OverloadCandidateSet CandidateSet; const RecordType *BaseRecord = Base->getType()->getAs<RecordType>(); - LookupResult R; - LookupQualifiedName(R, BaseRecord->getDecl(), OpName, LookupOrdinaryName); + if (RequireCompleteType(Base->getLocStart(), Base->getType(), + PDiag(diag::err_typecheck_incomplete_tag) + << Base->getSourceRange())) + return ExprError(); + + LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName); + LookupQualifiedName(R, BaseRecord->getDecl()); + R.suppressDiagnostics(); for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); Oper != OperEnd; ++Oper) diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h index 898393a..0d1f37a 100644 --- a/lib/Sema/SemaOverload.h +++ b/lib/Sema/SemaOverload.h @@ -156,6 +156,14 @@ namespace clang { /// object parameter of the conversion function. StandardConversionSequence Before; + /// EllipsisConversion - When this is true, it means user-defined + /// conversion sequence starts with a ... (elipsis) conversion, instead of + /// a standard conversion. In this case, 'Before' field must be ignored. + // FIXME. I much rather put this as the first field. But there seems to be + // a gcc code gen. bug which causes a crash in a test. Putting it here seems + // to work around the crash. + bool EllipsisConversion : 1; + /// After - Represents the standard conversion that occurs after /// the actual user-defined conversion. StandardConversionSequence After; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 6a65bd1..d0f214f 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -873,8 +873,7 @@ static bool IsReturnCopyElidable(ASTContext &Ctx, QualType RetType, if (!RetType->isRecordType()) return false; // ... the same cv-unqualified type as the function return type ... - if (Ctx.getCanonicalType(RetType).getUnqualifiedType() != - Ctx.getCanonicalType(ExprType).getUnqualifiedType()) + if (!Ctx.hasSameUnqualifiedType(RetType, ExprType)) return false; // ... the expression is the name of a non-volatile automatic object ... // We ignore parentheses here. @@ -965,9 +964,12 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) { // In C++ the return statement is handled via a copy initialization. // the C version of which boils down to CheckSingleAssignmentConstraints. // FIXME: Leaks RetValExp on error. - if (PerformCopyInitialization(RetValExp, FnRetType, "returning", Elidable)) + if (PerformCopyInitialization(RetValExp, FnRetType, "returning", Elidable)){ + // We should still clean up our temporaries, even when we're failing! + RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp, true); return StmtError(); - + } + if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 5ef3701..466a0e3 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -10,12 +10,14 @@ //===----------------------------------------------------------------------===/ #include "Sema.h" +#include "Lookup.h" #include "TreeTransform.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/Parse/DeclSpec.h" +#include "clang/Parse/Template.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/PartialDiagnostic.h" #include "llvm/Support/Compiler.h" @@ -129,29 +131,29 @@ TemplateNameKind Sema::isTemplateName(Scope *S, QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr); LookupCtx = computeDeclContext(ObjectType); isDependent = ObjectType->isDependentType(); + assert((isDependent || !ObjectType->isIncompleteType()) && + "Caller should have completed object type"); } else if (SS.isSet()) { // This nested-name-specifier occurs after another nested-name-specifier, // so long into the context associated with the prior nested-name-specifier. - LookupCtx = computeDeclContext(SS, EnteringContext); isDependent = isDependentScopeSpecifier(SS); + + // The declaration context must be complete. + if (LookupCtx && RequireCompleteDeclContext(SS)) + return TNK_Non_template; } - LookupResult Found; + LookupResult Found(*this, TName, SourceLocation(), LookupOrdinaryName); bool ObjectTypeSearchedInScope = 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(Found, LookupCtx); - // The declaration context must be complete. - if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS)) - return TNK_Non_template; - - LookupQualifiedName(Found, LookupCtx, TName, LookupOrdinaryName); - - if (ObjectTypePtr && Found.getKind() == LookupResult::NotFound) { + if (ObjectTypePtr && 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 @@ -164,7 +166,7 @@ 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, TName, LookupOrdinaryName); + LookupName(Found, S); ObjectTypeSearchedInScope = true; } } else if (isDependent) { @@ -172,7 +174,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, return TNK_Non_template; } else { // Perform unqualified name lookup in the current scope. - LookupName(Found, S, TName, LookupOrdinaryName); + LookupName(Found, S); } // FIXME: Cope with ambiguous name-lookup results. @@ -190,8 +192,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // template, the name is also looked up in the context of the entire // postfix-expression and [...] // - LookupResult FoundOuter; - LookupName(FoundOuter, S, TName, LookupOrdinaryName); + LookupResult FoundOuter(*this, TName, SourceLocation(), LookupOrdinaryName); + LookupName(FoundOuter, S); // FIXME: Handle ambiguities in this lookup better NamedDecl *OuterTemplate = isAcceptableTemplateName(Context, FoundOuter.getAsSingleDecl(Context)); @@ -283,6 +285,46 @@ TemplateDecl *Sema::AdjustDeclIfTemplate(DeclPtrTy &D) { return 0; } +static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, + const ParsedTemplateArgument &Arg) { + + switch (Arg.getKind()) { + case ParsedTemplateArgument::Type: { + DeclaratorInfo *DI; + QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI); + if (!DI) + DI = SemaRef.Context.getTrivialDeclaratorInfo(T, Arg.getLocation()); + return TemplateArgumentLoc(TemplateArgument(T), DI); + } + + case ParsedTemplateArgument::NonType: { + Expr *E = static_cast<Expr *>(Arg.getAsExpr()); + return TemplateArgumentLoc(TemplateArgument(E), E); + } + + case ParsedTemplateArgument::Template: { + TemplateName Template + = TemplateName::getFromVoidPointer(Arg.getAsTemplate().get()); + return TemplateArgumentLoc(TemplateArgument(Template), + Arg.getScopeSpec().getRange(), + Arg.getLocation()); + } + } + + llvm::llvm_unreachable("Unhandled parsed template argument"); + return TemplateArgumentLoc(); +} + +/// \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()); + + for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I) + TemplateArgs.push_back(translateTemplateArgument(*this, TemplateArgsIn[I])); +} + /// ActOnTypeParameter - Called when a C++ template type parameter /// (e.g., "typename T") has been parsed. Typename specifies whether /// the keyword "typename" was used to declare the type parameter @@ -517,34 +559,30 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S, /// parameter. void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD, SourceLocation EqualLoc, - ExprArg DefaultE) { + const ParsedTemplateArgument &Default) { TemplateTemplateParmDecl *TemplateParm = cast<TemplateTemplateParmDecl>(TemplateParamD.getAs<Decl>()); - - // Since a template-template parameter's default argument is an - // id-expression, it must be a DeclRefExpr. - DeclRefExpr *Default - = cast<DeclRefExpr>(static_cast<Expr *>(DefaultE.get())); - + // C++ [temp.param]p14: // A template-parameter shall not be used in its own default argument. // FIXME: Implement this check! Needs a recursive walk over the types. - // Check the well-formedness of the template argument. - if (!isa<TemplateDecl>(Default->getDecl())) { - Diag(Default->getSourceRange().getBegin(), - diag::err_template_arg_must_be_template) - << Default->getSourceRange(); - TemplateParm->setInvalidDecl(); - return; - } - if (CheckTemplateArgument(TemplateParm, Default)) { - TemplateParm->setInvalidDecl(); + // Check only that we have a template template argument. We don't want to + // try to check well-formedness now, because our template template parameter + // might have dependent types in its template parameters, which we wouldn't + // be able to match now. + // + // If none of the template template parameter's template arguments mention + // other template parameters, we could actually perform more checking here. + // However, it isn't worth doing. + TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default); + if (DefaultArg.getArgument().getAsTemplate().isNull()) { + Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template) + << DefaultArg.getSourceRange(); return; } - - DefaultE.release(); - TemplateParm->setDefaultArgument(Default); + + TemplateParm->setDefaultArgument(DefaultArg); } /// ActOnTemplateParameterList - Builds a TemplateParameterList that @@ -591,7 +629,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // Find any previous declaration with this name. DeclContext *SemanticContext; - LookupResult Previous; + LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName, + ForRedeclaration); if (SS.isNotEmpty() && !SS.isInvalid()) { if (RequireCompleteDeclContext(SS)) return true; @@ -602,11 +641,10 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, return true; } - LookupQualifiedName(Previous, SemanticContext, Name, LookupOrdinaryName, - true); + LookupQualifiedName(Previous, SemanticContext); } else { SemanticContext = CurContext; - LookupName(Previous, S, Name, LookupOrdinaryName, true); + LookupName(Previous, S); } assert(!Previous.isAmbiguous() && "Ambiguity in class template redecl?"); @@ -669,7 +707,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // Ensure that the template parameter lists are compatible. if (!TemplateParameterListsAreEqual(TemplateParams, PrevClassTemplate->getTemplateParameters(), - /*Complain=*/true)) + /*Complain=*/true, + TPL_TemplateMatch)) return true; // C++ [temp.class]p4: @@ -923,8 +962,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0; if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() && NewTemplateParm->hasDefaultArgument()) { - OldDefaultLoc = OldTemplateParm->getDefaultArgumentLoc(); - NewDefaultLoc = NewTemplateParm->getDefaultArgumentLoc(); + OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation(); + NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation(); SawDefaultArgument = true; RedundantDefaultArg = true; PreviousDefaultArgLoc = NewDefaultLoc; @@ -936,10 +975,12 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // that points to a previous template template parameter. NewTemplateParm->setDefaultArgument( OldTemplateParm->getDefaultArgument()); - PreviousDefaultArgLoc = OldTemplateParm->getDefaultArgumentLoc(); + PreviousDefaultArgLoc + = OldTemplateParm->getDefaultArgument().getLocation(); } else if (NewTemplateParm->hasDefaultArgument()) { SawDefaultArgument = true; - PreviousDefaultArgLoc = NewTemplateParm->getDefaultArgumentLoc(); + PreviousDefaultArgLoc + = NewTemplateParm->getDefaultArgument().getLocation(); } else if (SawDefaultArgument) MissingDefaultArg = true; } @@ -1085,7 +1126,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, if (ExpectedTemplateParams) TemplateParameterListsAreEqual(ParamLists[Idx], ExpectedTemplateParams, - true); + true, TPL_TemplateMatch); } } else if (ParamLists[Idx]->size() > 0) Diag(ParamLists[Idx]->getTemplateLoc(), @@ -1118,28 +1159,6 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, return ParamLists[NumParamLists - 1]; } -/// \brief Translates template arguments as provided by the parser -/// into template arguments used by semantic analysis. -void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, - SourceLocation *TemplateArgLocs, - llvm::SmallVector<TemplateArgumentLoc, 16> &TemplateArgs) { - TemplateArgs.reserve(TemplateArgsIn.size()); - - void **Args = TemplateArgsIn.getArgs(); - bool *ArgIsType = TemplateArgsIn.getArgIsType(); - for (unsigned Arg = 0, Last = TemplateArgsIn.size(); Arg != Last; ++Arg) { - if (ArgIsType[Arg]) { - DeclaratorInfo *DI; - QualType T = Sema::GetTypeFromParser(Args[Arg], &DI); - if (!DI) DI = Context.getTrivialDeclaratorInfo(T, TemplateArgLocs[Arg]); - TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(T), DI)); - } else { - Expr *E = reinterpret_cast<Expr *>(Args[Arg]); - TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(E), E)); - } - } -} - QualType Sema::CheckTemplateIdType(TemplateName Name, SourceLocation TemplateLoc, SourceLocation LAngleLoc, @@ -1169,7 +1188,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, QualType CanonType; - if (TemplateSpecializationType::anyDependentTemplateArguments( + if (Name.isDependent() || + TemplateSpecializationType::anyDependentTemplateArguments( TemplateArgs, NumTemplateArgs)) { // This class template specialization is a dependent @@ -1228,13 +1248,12 @@ Action::TypeResult Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation *TemplateArgLocsIn, SourceLocation RAngleLoc) { TemplateName Template = TemplateD.getAsVal<TemplateName>(); // Translate the parser's template argument list in our AST format. llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; - translateTemplateArguments(TemplateArgsIn, TemplateArgLocsIn, TemplateArgs); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc, TemplateArgs.data(), @@ -1336,13 +1355,12 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation *TemplateArgSLs, SourceLocation RAngleLoc) { TemplateName Template = TemplateD.getAsVal<TemplateName>(); // Translate the parser's template argument list in our AST format. llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; - translateTemplateArguments(TemplateArgsIn, TemplateArgSLs, TemplateArgs); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); TemplateArgsIn.release(); return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(), @@ -1449,6 +1467,333 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, return false; } +/// \brief Substitute template arguments into the default template argument for +/// the given template type parameter. +/// +/// \param SemaRef the semantic analysis object for which we are performing +/// the substitution. +/// +/// \param Template the template that we are synthesizing template arguments +/// for. +/// +/// \param TemplateLoc the location of the template name that started the +/// template-id we are checking. +/// +/// \param RAngleLoc the location of the right angle bracket ('>') that +/// terminates the template-id. +/// +/// \param Param the template template parameter whose default we are +/// substituting into. +/// +/// \param Converted the list of template arguments provided for template +/// parameters that precede \p Param in the template parameter list. +/// +/// \returns the substituted template argument, or NULL if an error occurred. +static DeclaratorInfo * +SubstDefaultTemplateArgument(Sema &SemaRef, + TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + TemplateTypeParmDecl *Param, + TemplateArgumentListBuilder &Converted) { + DeclaratorInfo *ArgType = Param->getDefaultArgumentInfo(); + + // If the argument type is dependent, instantiate it now based + // on the previously-computed template arguments. + if (ArgType->getType()->isDependentType()) { + TemplateArgumentList TemplateArgs(SemaRef.Context, Converted, + /*TakeArgs=*/false); + + MultiLevelTemplateArgumentList AllTemplateArgs + = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs); + + Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, + Template, Converted.getFlatArguments(), + Converted.flatSize(), + SourceRange(TemplateLoc, RAngleLoc)); + + ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs, + Param->getDefaultArgumentLoc(), + Param->getDeclName()); + } + + return ArgType; +} + +/// \brief Substitute template arguments into the default template argument for +/// the given non-type template parameter. +/// +/// \param SemaRef the semantic analysis object for which we are performing +/// the substitution. +/// +/// \param Template the template that we are synthesizing template arguments +/// for. +/// +/// \param TemplateLoc the location of the template name that started the +/// template-id we are checking. +/// +/// \param RAngleLoc the location of the right angle bracket ('>') that +/// terminates the template-id. +/// +/// \param Param the non-type template parameter whose default we are +/// substituting into. +/// +/// \param Converted the list of template arguments provided for template +/// parameters that precede \p Param in the template parameter list. +/// +/// \returns the substituted template argument, or NULL if an error occurred. +static Sema::OwningExprResult +SubstDefaultTemplateArgument(Sema &SemaRef, + TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + NonTypeTemplateParmDecl *Param, + TemplateArgumentListBuilder &Converted) { + TemplateArgumentList TemplateArgs(SemaRef.Context, Converted, + /*TakeArgs=*/false); + + MultiLevelTemplateArgumentList AllTemplateArgs + = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs); + + Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, + Template, Converted.getFlatArguments(), + Converted.flatSize(), + SourceRange(TemplateLoc, RAngleLoc)); + + return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs); +} + +/// \brief Substitute template arguments into the default template argument for +/// the given template template parameter. +/// +/// \param SemaRef the semantic analysis object for which we are performing +/// the substitution. +/// +/// \param Template the template that we are synthesizing template arguments +/// for. +/// +/// \param TemplateLoc the location of the template name that started the +/// template-id we are checking. +/// +/// \param RAngleLoc the location of the right angle bracket ('>') that +/// terminates the template-id. +/// +/// \param Param the template template parameter whose default we are +/// substituting into. +/// +/// \param Converted the list of template arguments provided for template +/// parameters that precede \p Param in the template parameter list. +/// +/// \returns the substituted template argument, or NULL if an error occurred. +static TemplateName +SubstDefaultTemplateArgument(Sema &SemaRef, + TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + TemplateTemplateParmDecl *Param, + TemplateArgumentListBuilder &Converted) { + TemplateArgumentList TemplateArgs(SemaRef.Context, Converted, + /*TakeArgs=*/false); + + MultiLevelTemplateArgumentList AllTemplateArgs + = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs); + + Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, + Template, Converted.getFlatArguments(), + Converted.flatSize(), + SourceRange(TemplateLoc, RAngleLoc)); + + return SemaRef.SubstTemplateName( + Param->getDefaultArgument().getArgument().getAsTemplate(), + Param->getDefaultArgument().getTemplateNameLoc(), + AllTemplateArgs); +} + +/// \brief Check that the given template argument corresponds to the given +/// template parameter. +bool Sema::CheckTemplateArgument(NamedDecl *Param, + const TemplateArgumentLoc &Arg, + TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + TemplateArgumentListBuilder &Converted) { + // Check template type parameters. + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) + return CheckTemplateTypeArgument(TTP, Arg, Converted); + + // Check non-type template parameters. + if (NonTypeTemplateParmDecl *NTTP =dyn_cast<NonTypeTemplateParmDecl>(Param)) { + // Do substitution on the type of the non-type template parameter + // with the template arguments we've seen thus far. + QualType NTTPType = NTTP->getType(); + if (NTTPType->isDependentType()) { + // Do substitution on the type of the non-type template parameter. + InstantiatingTemplate Inst(*this, TemplateLoc, Template, + NTTP, Converted.getFlatArguments(), + Converted.flatSize(), + SourceRange(TemplateLoc, RAngleLoc)); + + TemplateArgumentList TemplateArgs(Context, Converted, + /*TakeArgs=*/false); + NTTPType = SubstType(NTTPType, + MultiLevelTemplateArgumentList(TemplateArgs), + NTTP->getLocation(), + NTTP->getDeclName()); + // If that worked, check the non-type template parameter type + // for validity. + if (!NTTPType.isNull()) + NTTPType = CheckNonTypeTemplateParameterType(NTTPType, + NTTP->getLocation()); + if (NTTPType.isNull()) + return true; + } + + switch (Arg.getArgument().getKind()) { + case TemplateArgument::Null: + assert(false && "Should never see a NULL template argument here"); + return true; + + case TemplateArgument::Expression: { + Expr *E = Arg.getArgument().getAsExpr(); + TemplateArgument Result; + if (CheckTemplateArgument(NTTP, NTTPType, E, Result)) + return true; + + Converted.Append(Result); + break; + } + + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + // We've already checked this template argument, so just copy + // it to the list of converted arguments. + Converted.Append(Arg.getArgument()); + break; + + case TemplateArgument::Template: + // We were given a template template argument. It may not be ill-formed; + // see below. + if (DependentTemplateName *DTN + = Arg.getArgument().getAsTemplate().getAsDependentTemplateName()) { + // We have a template argument such as \c T::template X, which we + // 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(), + Arg.getTemplateQualifierRange(), + DTN->getQualifier(), + /*isAddressOfOperand=*/false); + + TemplateArgument Result; + if (CheckTemplateArgument(NTTP, NTTPType, E, Result)) + return true; + + Converted.Append(Result); + break; + } + + // We have a template argument that actually does refer to a class + // template, template alias, or template template parameter, and + // therefore cannot be a non-type template argument. + Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr) + << Arg.getSourceRange(); + + Diag(Param->getLocation(), diag::note_template_param_here); + return true; + + case TemplateArgument::Type: { + // We have a non-type template parameter but the template + // argument is a type. + + // C++ [temp.arg]p2: + // In a template-argument, an ambiguity between a type-id and + // an expression is resolved to a type-id, regardless of the + // form of the corresponding template-parameter. + // + // We warn specifically about this case, since it can be rather + // confusing for users. + QualType T = Arg.getArgument().getAsType(); + SourceRange SR = Arg.getSourceRange(); + if (T->isFunctionType()) + Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) << SR << T; + else + Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR; + Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + case TemplateArgument::Pack: + llvm::llvm_unreachable("Caller must expand template argument packs"); + break; + } + + return false; + } + + + // Check template template parameters. + TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(Param); + + // Substitute into the template parameter list of the template + // template parameter, since previously-supplied template arguments + // may appear within the template template parameter. + { + // Set up a template instantiation context. + LocalInstantiationScope Scope(*this); + InstantiatingTemplate Inst(*this, TemplateLoc, Template, + TempParm, Converted.getFlatArguments(), + Converted.flatSize(), + SourceRange(TemplateLoc, RAngleLoc)); + + TemplateArgumentList TemplateArgs(Context, Converted, + /*TakeArgs=*/false); + TempParm = cast_or_null<TemplateTemplateParmDecl>( + SubstDecl(TempParm, CurContext, + MultiLevelTemplateArgumentList(TemplateArgs))); + if (!TempParm) + return true; + + // FIXME: TempParam is leaked. + } + + switch (Arg.getArgument().getKind()) { + case TemplateArgument::Null: + assert(false && "Should never see a NULL template argument here"); + return true; + + case TemplateArgument::Template: + if (CheckTemplateArgument(TempParm, Arg)) + return true; + + Converted.Append(Arg.getArgument()); + break; + + case TemplateArgument::Expression: + case TemplateArgument::Type: + // We have a template template parameter but the template + // argument does not refer to a template. + Diag(Arg.getLocation(), diag::err_template_arg_must_be_template); + return true; + + case TemplateArgument::Declaration: + llvm::llvm_unreachable( + "Declaration argument with template template parameter"); + break; + case TemplateArgument::Integral: + llvm::llvm_unreachable( + "Integral argument with template template parameter"); + break; + + case TemplateArgument::Pack: + llvm::llvm_unreachable("Caller must expand template argument packs"); + break; + } + + return false; +} + /// \brief Check that the given template argument list is well-formed /// for specializing the given template. bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, @@ -1499,226 +1844,105 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (ArgIdx > NumArgs && PartialTemplateArgs) break; - // Decode the template argument - TemplateArgumentLoc Arg; - - if (ArgIdx >= NumArgs) { - // Retrieve the default template argument from the template - // parameter. - if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) { - if (TTP->isParameterPack()) { - // We have an empty argument pack. - Converted.BeginPack(); - Converted.EndPack(); - break; - } - - if (!TTP->hasDefaultArgument()) + // If we have a template parameter pack, check every remaining template + // argument against that template parameter pack. + if ((*Param)->isTemplateParameterPack()) { + Converted.BeginPack(); + for (; ArgIdx < NumArgs; ++ArgIdx) { + if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template, + TemplateLoc, RAngleLoc, Converted)) { + Invalid = true; break; - - DeclaratorInfo *ArgType = TTP->getDefaultArgumentInfo(); - - // If the argument type is dependent, instantiate it now based - // on the previously-computed template arguments. - if (ArgType->getType()->isDependentType()) { - InstantiatingTemplate Inst(*this, TemplateLoc, - Template, Converted.getFlatArguments(), - Converted.flatSize(), - SourceRange(TemplateLoc, RAngleLoc)); - - TemplateArgumentList TemplateArgs(Context, Converted, - /*TakeArgs=*/false); - ArgType = SubstType(ArgType, - MultiLevelTemplateArgumentList(TemplateArgs), - TTP->getDefaultArgumentLoc(), - TTP->getDeclName()); } - - if (!ArgType) - return true; - - Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()), ArgType); - } else if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { - if (!NTTP->hasDefaultArgument()) - break; - - InstantiatingTemplate Inst(*this, TemplateLoc, - Template, Converted.getFlatArguments(), - Converted.flatSize(), - SourceRange(TemplateLoc, RAngleLoc)); - - TemplateArgumentList TemplateArgs(Context, Converted, - /*TakeArgs=*/false); - - Sema::OwningExprResult E - = SubstExpr(NTTP->getDefaultArgument(), - MultiLevelTemplateArgumentList(TemplateArgs)); - if (E.isInvalid()) - return true; - - Expr *Ex = E.takeAs<Expr>(); - Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex); - } else { - TemplateTemplateParmDecl *TempParm - = cast<TemplateTemplateParmDecl>(*Param); - - if (!TempParm->hasDefaultArgument()) - break; - - // FIXME: Subst default argument - Arg = TemplateArgumentLoc(TemplateArgument(TempParm->getDefaultArgument()), - TempParm->getDefaultArgument()); } - } else { - // Retrieve the template argument produced by the user. - Arg = TemplateArgs[ArgIdx]; + Converted.EndPack(); + continue; } - - + + if (ArgIdx < NumArgs) { + // Check the template argument we were given. + if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template, + TemplateLoc, RAngleLoc, Converted)) + return true; + + continue; + } + + // We have a default template argument that we will use. + TemplateArgumentLoc Arg; + + // Retrieve the default template argument from the template + // parameter. For each kind of template parameter, we substitute the + // template arguments provided thus far and any "outer" template arguments + // (when the template parameter was part of a nested template) into + // the default argument. if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) { - if (TTP->isParameterPack()) { - Converted.BeginPack(); - // Check all the remaining arguments (if any). - for (; ArgIdx < NumArgs; ++ArgIdx) { - if (CheckTemplateTypeArgument(TTP, TemplateArgs[ArgIdx], Converted)) - Invalid = true; - } - - Converted.EndPack(); - } else { - if (CheckTemplateTypeArgument(TTP, Arg, Converted)) - Invalid = true; + if (!TTP->hasDefaultArgument()) { + assert((Invalid || PartialTemplateArgs) && "Missing default argument"); + break; } + + DeclaratorInfo *ArgType = SubstDefaultTemplateArgument(*this, + Template, + TemplateLoc, + RAngleLoc, + TTP, + Converted); + if (!ArgType) + return true; + + Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()), + ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { - // Check non-type template parameters. - - // Do substitution on the type of the non-type template parameter - // with the template arguments we've seen thus far. - QualType NTTPType = NTTP->getType(); - if (NTTPType->isDependentType()) { - // Do substitution on the type of the non-type template parameter. - InstantiatingTemplate Inst(*this, TemplateLoc, - Template, Converted.getFlatArguments(), - Converted.flatSize(), - SourceRange(TemplateLoc, RAngleLoc)); - - TemplateArgumentList TemplateArgs(Context, Converted, - /*TakeArgs=*/false); - NTTPType = SubstType(NTTPType, - MultiLevelTemplateArgumentList(TemplateArgs), - NTTP->getLocation(), - NTTP->getDeclName()); - // If that worked, check the non-type template parameter type - // for validity. - if (!NTTPType.isNull()) - NTTPType = CheckNonTypeTemplateParameterType(NTTPType, - NTTP->getLocation()); - if (NTTPType.isNull()) { - Invalid = true; - break; - } - } - - switch (Arg.getArgument().getKind()) { - case TemplateArgument::Null: - assert(false && "Should never see a NULL template argument here"); - break; - - case TemplateArgument::Expression: { - Expr *E = Arg.getArgument().getAsExpr(); - TemplateArgument Result; - if (CheckTemplateArgument(NTTP, NTTPType, E, Result)) - Invalid = true; - else - Converted.Append(Result); + if (!NTTP->hasDefaultArgument()) { + assert((Invalid || PartialTemplateArgs) && "Missing default argument"); break; } - case TemplateArgument::Declaration: - case TemplateArgument::Integral: - // We've already checked this template argument, so just copy - // it to the list of converted arguments. - Converted.Append(Arg.getArgument()); - break; - - case TemplateArgument::Type: { - // We have a non-type template parameter but the template - // argument is a type. - - // C++ [temp.arg]p2: - // In a template-argument, an ambiguity between a type-id and - // an expression is resolved to a type-id, regardless of the - // form of the corresponding template-parameter. - // - // We warn specifically about this case, since it can be rather - // confusing for users. - QualType T = Arg.getArgument().getAsType(); - SourceRange SR = Arg.getSourceRange(); - if (T->isFunctionType()) - Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) - << SR << T; - else - Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR; - Diag((*Param)->getLocation(), diag::note_template_param_here); - Invalid = true; - break; - } + Sema::OwningExprResult E = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + NTTP, + Converted); + if (E.isInvalid()) + return true; - case TemplateArgument::Pack: - assert(0 && "FIXME: Implement!"); - break; - } + Expr *Ex = E.takeAs<Expr>(); + Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex); } else { - // Check template template parameters. TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(*Param); - switch (Arg.getArgument().getKind()) { - case TemplateArgument::Null: - assert(false && "Should never see a NULL template argument here"); + if (!TempParm->hasDefaultArgument()) { + assert((Invalid || PartialTemplateArgs) && "Missing default argument"); break; - - case TemplateArgument::Expression: { - Expr *ArgExpr = Arg.getArgument().getAsExpr(); - if (ArgExpr && isa<DeclRefExpr>(ArgExpr) && - isa<TemplateDecl>(cast<DeclRefExpr>(ArgExpr)->getDecl())) { - if (CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr))) - Invalid = true; - - // Add the converted template argument. - Decl *D - = cast<DeclRefExpr>(ArgExpr)->getDecl()->getCanonicalDecl(); - Converted.Append(TemplateArgument(D)); - continue; - } } - // fall through - case TemplateArgument::Type: { - // We have a template template parameter but the template - // argument does not refer to a template. - Diag(Arg.getLocation(), diag::err_template_arg_must_be_template); - Invalid = true; - break; - } - - case TemplateArgument::Declaration: - // We've already checked this template argument, so just copy - // it to the list of converted arguments. - Converted.Append(Arg.getArgument()); - break; - - case TemplateArgument::Integral: - assert(false && "Integral argument with template template parameter"); - break; - - case TemplateArgument::Pack: - assert(0 && "FIXME: Implement!"); - break; - } + TemplateName Name = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + TempParm, + Converted); + if (Name.isNull()) + return true; + + Arg = TemplateArgumentLoc(TemplateArgument(Name), + TempParm->getDefaultArgument().getTemplateQualifierRange(), + TempParm->getDefaultArgument().getTemplateNameLoc()); } + + // Introduce an instantiation record that describes where we are using + // the default template argument. + InstantiatingTemplate Instantiating(*this, RAngleLoc, Template, *Param, + Converted.getFlatArguments(), + Converted.flatSize(), + SourceRange(TemplateLoc, RAngleLoc)); + + // Check the default template argument. + if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, + RAngleLoc, Converted)) + return true; } return Invalid; @@ -1864,8 +2088,8 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, /// \brief Checks whether the given template argument is a pointer to /// member constant according to C++ [temp.arg.nontype]p1. -bool -Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { +bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, + TemplateArgument &Converted) { bool Invalid = false; // See through any implicit casts we added to fix the type. @@ -1896,13 +2120,33 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { Arg = Parens->getSubExpr(); } - if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) + // A pointer-to-member constant written &Class::member. + if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) { if (UnOp->getOpcode() == UnaryOperator::AddrOf) { DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr()); if (DRE && !DRE->getQualifier()) DRE = 0; } - + } + // A constant of pointer-to-member type. + else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) { + if (ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) { + if (VD->getType()->isMemberPointerType()) { + if (isa<NonTypeTemplateParmDecl>(VD) || + (isa<VarDecl>(VD) && + Context.getCanonicalType(VD->getType()).isConstQualified())) { + if (Arg->isTypeDependent() || Arg->isValueDependent()) + Converted = TemplateArgument(Arg->Retain()); + else + Converted = TemplateArgument(VD->getCanonicalDecl()); + return Invalid; + } + } + } + + DRE = 0; + } + if (!DRE) return Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_pointer_to_member_form) @@ -1915,7 +2159,10 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { // Okay: this is the address of a non-static member, and therefore // a member pointer constant. - Member = DRE->getDecl(); + if (Arg->isTypeDependent() || Arg->isValueDependent()) + Converted = TemplateArgument(Arg->Retain()); + else + Converted = TemplateArgument(DRE->getDecl()->getCanonicalDecl()); return Invalid; } @@ -2119,16 +2366,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; } - if (ParamType->isMemberPointerType()) { - NamedDecl *Member = 0; - if (CheckTemplateArgumentPointerToMember(Arg, Member)) - return true; - - if (Member) - Member = cast<NamedDecl>(Member->getCanonicalDecl()); - Converted = TemplateArgument(Member); - return false; - } + if (ParamType->isMemberPointerType()) + return CheckTemplateArgumentPointerToMember(Arg, Converted); NamedDecl *Entity = 0; if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity)) @@ -2241,14 +2480,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; } - NamedDecl *Member = 0; - if (CheckTemplateArgumentPointerToMember(Arg, Member)) - return true; - - if (Member) - Member = cast<NamedDecl>(Member->getCanonicalDecl()); - Converted = TemplateArgument(Member); - return false; + return CheckTemplateArgumentPointerToMember(Arg, Converted); } /// \brief Check a template argument against its corresponding @@ -2257,9 +2489,14 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, /// This routine implements the semantics of C++ [temp.arg.template]. /// It returns true if an error occurred, and false otherwise. bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, - DeclRefExpr *Arg) { - assert(isa<TemplateDecl>(Arg->getDecl()) && "Only template decls allowed"); - TemplateDecl *Template = cast<TemplateDecl>(Arg->getDecl()); + const TemplateArgumentLoc &Arg) { + TemplateName Name = Arg.getArgument().getAsTemplate(); + TemplateDecl *Template = Name.getAsTemplateDecl(); + if (!Template) { + // Any dependent template name is fine. + assert(Name.isDependent() && "Non-dependent template isn't a declaration?"); + return false; + } // C++ [temp.arg.template]p1: // A template-argument for a template template-parameter shall be @@ -2276,15 +2513,16 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, !isa<TemplateTemplateParmDecl>(Template)) { assert(isa<FunctionTemplateDecl>(Template) && "Only function templates are possible here"); - Diag(Arg->getLocStart(), diag::err_template_arg_not_class_template); + Diag(Arg.getLocation(), diag::err_template_arg_not_class_template); Diag(Template->getLocation(), diag::note_template_arg_refers_here_func) << Template; } return !TemplateParameterListsAreEqual(Template->getTemplateParameters(), Param->getTemplateParameters(), - true, true, - Arg->getSourceRange().getBegin()); + true, + TPL_TemplateTemplateArgumentMatch, + Arg.getLocation()); } /// \brief Determine whether the given template parameter lists are @@ -2300,9 +2538,7 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, /// \param Complain If true, this routine will produce a diagnostic if /// the template parameter lists are not equivalent. /// -/// \param IsTemplateTemplateParm If true, this routine is being -/// called to compare the template parameter lists of a template -/// template parameter. +/// \param Kind describes how we are to match the template parameter lists. /// /// \param TemplateArgLoc If this source location is valid, then we /// are actually checking the template parameter list of a template @@ -2316,7 +2552,7 @@ bool Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, TemplateParameterList *Old, bool Complain, - bool IsTemplateTemplateParm, + TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) { if (Old->size() != New->size()) { if (Complain) { @@ -2327,10 +2563,10 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, } Diag(New->getTemplateLoc(), NextDiag) << (New->size() > Old->size()) - << IsTemplateTemplateParm + << (Kind != TPL_TemplateMatch) << SourceRange(New->getTemplateLoc(), New->getRAngleLoc()); Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration) - << IsTemplateTemplateParm + << (Kind != TPL_TemplateMatch) << SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc()); } @@ -2348,9 +2584,9 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, NextDiag = diag::note_template_param_different_kind; } Diag((*NewParm)->getLocation(), NextDiag) - << IsTemplateTemplateParm; + << (Kind != TPL_TemplateMatch); Diag((*OldParm)->getLocation(), diag::note_template_prev_declaration) - << IsTemplateTemplateParm; + << (Kind != TPL_TemplateMatch); } return false; } @@ -2358,26 +2594,21 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, if (isa<TemplateTypeParmDecl>(*OldParm)) { // Okay; all template type parameters are equivalent (since we // know we're at the same index). -#if 0 - // FIXME: Enable this code in debug mode *after* we properly go through - // and "instantiate" the template parameter lists of template template - // parameters. It's only after this instantiation that (1) any dependent - // types within the template parameter list of the template template - // parameter can be checked, and (2) the template type parameter depths - // will match up. - QualType OldParmType - = Context.getTypeDeclType(cast<TemplateTypeParmDecl>(*OldParm)); - QualType NewParmType - = Context.getTypeDeclType(cast<TemplateTypeParmDecl>(*NewParm)); - assert(Context.getCanonicalType(OldParmType) == - Context.getCanonicalType(NewParmType) && - "type parameter mismatch?"); -#endif } else if (NonTypeTemplateParmDecl *OldNTTP = dyn_cast<NonTypeTemplateParmDecl>(*OldParm)) { // The types of non-type template parameters must agree. NonTypeTemplateParmDecl *NewNTTP = cast<NonTypeTemplateParmDecl>(*NewParm); + + // If we are matching a template template argument to a template + // template parameter and one of the non-type template parameter types + // is dependent, then we must wait until template instantiation time + // to actually compare the arguments. + if (Kind == TPL_TemplateTemplateArgumentMatch && + (OldNTTP->getType()->isDependentType() || + NewNTTP->getType()->isDependentType())) + continue; + if (Context.getCanonicalType(OldNTTP->getType()) != Context.getCanonicalType(NewNTTP->getType())) { if (Complain) { @@ -2389,7 +2620,7 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, } Diag(NewNTTP->getLocation(), NextDiag) << NewNTTP->getType() - << IsTemplateTemplateParm; + << (Kind != TPL_TemplateMatch); Diag(OldNTTP->getLocation(), diag::note_template_nontype_parm_prev_declaration) << OldNTTP->getType(); @@ -2399,7 +2630,6 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, } else { // The template parameter lists of template template // parameters must agree. - // FIXME: Could we perform a faster "type" comparison here? assert(isa<TemplateTemplateParmDecl>(*OldParm) && "Only template template parameters handled here"); TemplateTemplateParmDecl *OldTTP @@ -2409,7 +2639,7 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, if (!TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(), OldTTP->getTemplateParameters(), Complain, - /*IsTemplateTemplateParm=*/true, + (Kind == TPL_TemplateMatch? TPL_TemplateTemplateParmMatch : Kind), TemplateArgLoc)) return false; } @@ -2635,16 +2865,9 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs( } else if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>( TemplateParams->getParam(I))) { - // FIXME: We should settle on either Declaration storage or - // Expression storage for template template parameters. + TemplateName Name = ArgList[I].getAsTemplate(); TemplateTemplateParmDecl *ArgDecl - = dyn_cast_or_null<TemplateTemplateParmDecl>( - ArgList[I].getAsDecl()); - if (!ArgDecl) - if (DeclRefExpr *DRE - = dyn_cast_or_null<DeclRefExpr>(ArgList[I].getAsExpr())) - ArgDecl = dyn_cast<TemplateTemplateParmDecl>(DRE->getDecl()); - + = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl()); if (!ArgDecl || ArgDecl->getIndex() != TTP->getIndex() || ArgDecl->getDepth() != TTP->getDepth()) @@ -2724,7 +2947,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc, AttributeList *Attr, MultiTemplateParamsArg TemplateParameterLists) { @@ -2733,7 +2955,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Find the class template we're specializing TemplateName Name = TemplateD.getAsVal<TemplateName>(); ClassTemplateDecl *ClassTemplate - = cast<ClassTemplateDecl>(Name.getAsTemplateDecl()); + = dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl()); + + if (!ClassTemplate) { + Diag(TemplateNameLoc, diag::err_not_class_template_specialization) + << (Name.getAsTemplateDecl() && + isa<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())); + return true; + } bool isExplicitSpecialization = false; bool isPartialSpecialization = false; @@ -2772,12 +3001,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, } } else { TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param); - if (Expr *DefArg = TTP->getDefaultArgument()) { - Diag(TTP->getDefaultArgumentLoc(), + if (TTP->hasDefaultArgument()) { + Diag(TTP->getDefaultArgument().getLocation(), diag::err_default_arg_in_partial_spec) - << DefArg->getSourceRange(); - TTP->setDefaultArgument(0); - DefArg->Destroy(Context); + << TTP->getDefaultArgument().getSourceRange(); + TTP->setDefaultArgument(TemplateArgumentLoc()); } } } @@ -2819,7 +3047,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Translate the parser's template argument list in our AST format. llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; - translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); // Check that the template argument list is well-formed for this // template. @@ -3625,7 +3853,6 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc, AttributeList *Attr) { // Find the class template we're specializing @@ -3664,7 +3891,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Translate the parser's template argument list in our AST format. llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; - translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); // Check that the template argument list is well-formed for this // template. @@ -3966,19 +4193,16 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition : TSK_ExplicitInstantiationDeclaration; - LookupResult Previous; - LookupParsedName(Previous, S, &D.getCXXScopeSpec(), - Name, LookupOrdinaryName); + LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName); + LookupParsedName(Previous, S, &D.getCXXScopeSpec()); if (!R->isFunctionType()) { // C++ [temp.explicit]p1: // A [...] static data member of a class template can be explicitly // instantiated from the member definition associated with its class // template. - if (Previous.isAmbiguous()) { - return DiagnoseAmbiguousLookup(Previous, Name, D.getIdentifierLoc(), - D.getSourceRange()); - } + if (Previous.isAmbiguous()) + return true; VarDecl *Prev = dyn_cast_or_null<VarDecl>( Previous.getAsSingleDecl(Context)); @@ -4047,10 +4271,8 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, TemplateIdAnnotation *TemplateId = D.getName().TemplateId; ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), - TemplateId->getTemplateArgIsType(), TemplateId->NumArgs); translateTemplateArguments(TemplateArgsPtr, - TemplateId->getTemplateArgLocations(), TemplateArgs); HasExplicitTemplateArgs = true; TemplateArgsPtr.release(); @@ -4259,11 +4481,11 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, assert(Ctx && "No declaration context?"); DeclarationName Name(&II); - LookupResult Result; - LookupQualifiedName(Result, Ctx, Name, LookupOrdinaryName, false); + LookupResult Result(*this, Name, Range.getEnd(), LookupOrdinaryName); + LookupQualifiedName(Result, Ctx); unsigned DiagID = 0; Decl *Referenced = 0; - switch (Result.getKind()) { + switch (Result.getResultKind()) { case LookupResult::NotFound: DiagID = diag::err_typename_nested_not_found; break; @@ -4280,13 +4502,16 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, Referenced = Result.getFoundDecl(); break; + case LookupResult::FoundUnresolvedValue: + llvm::llvm_unreachable("unresolved using decl in non-dependent context"); + return QualType(); + case LookupResult::FoundOverloaded: DiagID = diag::err_typename_nested_not_type; Referenced = *Result.begin(); break; case LookupResult::Ambiguous: - DiagnoseAmbiguousLookup(Result, Name, Range.getEnd(), Range); return QualType(); } @@ -4436,12 +4661,24 @@ QualType Sema::RebuildTypeInCurrentInstantiation(QualType T, SourceLocation Loc, std::string Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args) { + // FIXME: For variadic templates, we'll need to get the structured list. + return getTemplateArgumentBindingsText(Params, Args.getFlatArgumentList(), + Args.flat_size()); +} + +std::string +Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, + const TemplateArgument *Args, + unsigned NumArgs) { std::string Result; - if (!Params || Params->size() == 0) + if (!Params || Params->size() == 0 || NumArgs == 0) return Result; for (unsigned I = 0, N = Params->size(); I != N; ++I) { + if (I >= NumArgs) + break; + if (I == 0) Result += "[with "; else @@ -4484,6 +4721,14 @@ Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, break; } + case TemplateArgument::Template: { + std::string Str; + llvm::raw_string_ostream OS(Str); + Args[I].getAsTemplate().print(OS, Context.PrintingPolicy); + Result += OS.str(); + break; + } + case TemplateArgument::Integral: { Result += Args[I].getAsIntegral()->toString(10); break; diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 7b5ad7f..10594c7 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -126,7 +126,6 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, /// from the given type- or value-dependent expression. /// /// \returns true if deduction succeeded, false otherwise. - static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(ASTContext &Context, NonTypeTemplateParmDecl *NTTP, @@ -166,34 +165,87 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, return Sema::TDK_Success; } +/// \brief Deduce the value of the given non-type template parameter +/// from the given declaration. +/// +/// \returns true if deduction succeeded, false otherwise. +static Sema::TemplateDeductionResult +DeduceNonTypeTemplateArgument(ASTContext &Context, + NonTypeTemplateParmDecl *NTTP, + Decl *D, + Sema::TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<TemplateArgument> &Deduced) { + assert(NTTP->getDepth() == 0 && + "Cannot deduce non-type template argument with depth > 0"); + + if (Deduced[NTTP->getIndex()].isNull()) { + Deduced[NTTP->getIndex()] = TemplateArgument(D->getCanonicalDecl()); + return Sema::TDK_Success; + } + + if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Expression) { + // Okay, we deduced a declaration in one case and a dependent expression + // in another case. + return Sema::TDK_Success; + } + + if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Declaration) { + // Compare the declarations for equality + if (Deduced[NTTP->getIndex()].getAsDecl()->getCanonicalDecl() == + D->getCanonicalDecl()) + return Sema::TDK_Success; + + // FIXME: Fill in argument mismatch information + return Sema::TDK_NonDeducedMismatch; + } + + return Sema::TDK_Success; +} + static Sema::TemplateDeductionResult DeduceTemplateArguments(ASTContext &Context, + TemplateParameterList *TemplateParams, TemplateName Param, TemplateName Arg, Sema::TemplateDeductionInfo &Info, llvm::SmallVectorImpl<TemplateArgument> &Deduced) { - // FIXME: Implement template argument deduction for template - // template parameters. - - // FIXME: this routine does not have enough information to produce - // good diagnostics. - TemplateDecl *ParamDecl = Param.getAsTemplateDecl(); - TemplateDecl *ArgDecl = Arg.getAsTemplateDecl(); - - if (!ParamDecl || !ArgDecl) { - // FIXME: fill in Info.Param/Info.FirstArg - return Sema::TDK_Inconsistent; + if (!ParamDecl) { + // The parameter type is dependent and is not a template template parameter, + // so there is nothing that we can deduce. + return Sema::TDK_Success; } - - ParamDecl = cast<TemplateDecl>(ParamDecl->getCanonicalDecl()); - ArgDecl = cast<TemplateDecl>(ArgDecl->getCanonicalDecl()); - if (ParamDecl != ArgDecl) { - // FIXME: fill in Info.Param/Info.FirstArg + + if (TemplateTemplateParmDecl *TempParam + = dyn_cast<TemplateTemplateParmDecl>(ParamDecl)) { + // Bind the template template parameter to the given template name. + TemplateArgument &ExistingArg = Deduced[TempParam->getIndex()]; + if (ExistingArg.isNull()) { + // This is the first deduction for this template template parameter. + ExistingArg = TemplateArgument(Context.getCanonicalTemplateName(Arg)); + return Sema::TDK_Success; + } + + // Verify that the previous binding matches this deduction. + assert(ExistingArg.getKind() == TemplateArgument::Template); + if (Context.hasSameTemplateName(ExistingArg.getAsTemplate(), Arg)) + return Sema::TDK_Success; + + // Inconsistent deduction. + Info.Param = TempParam; + Info.FirstArg = ExistingArg; + Info.SecondArg = TemplateArgument(Arg); return Sema::TDK_Inconsistent; } - - return Sema::TDK_Success; + + // Verify that the two template names are equivalent. + if (Context.hasSameTemplateName(Param, Arg)) + return Sema::TDK_Success; + + // Mismatch of non-dependent template parameter to argument. + Info.FirstArg = TemplateArgument(Param); + Info.SecondArg = TemplateArgument(Arg); + return Sema::TDK_NonDeducedMismatch; } /// \brief Deduce the template arguments by comparing the template parameter @@ -224,32 +276,20 @@ DeduceTemplateArguments(ASTContext &Context, assert(Arg.isCanonical() && "Argument type must be canonical"); // Check whether the template argument is a dependent template-id. - // FIXME: This is untested code; it can be tested when we implement - // partial ordering of class template partial specializations. if (const TemplateSpecializationType *SpecArg = dyn_cast<TemplateSpecializationType>(Arg)) { // Perform template argument deduction for the template name. if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(Context, + = DeduceTemplateArguments(Context, TemplateParams, Param->getTemplateName(), SpecArg->getTemplateName(), Info, Deduced)) return Result; - unsigned NumArgs = Param->getNumArgs(); - - // FIXME: When one of the template-names refers to a - // declaration with default template arguments, do we need to - // fill in those default template arguments here? Most likely, - // the answer is "yes", but I don't see any references. This - // issue may be resolved elsewhere, because we may want to - // instantiate default template arguments when we actually write - // the template-id. - if (SpecArg->getNumArgs() != NumArgs) - return Sema::TDK_NonDeducedMismatch; // Perform template argument deduction on each template // argument. + unsigned NumArgs = std::min(SpecArg->getNumArgs(), Param->getNumArgs()); for (unsigned I = 0; I != NumArgs; ++I) if (Sema::TemplateDeductionResult Result = DeduceTemplateArguments(Context, TemplateParams, @@ -276,13 +316,12 @@ DeduceTemplateArguments(ASTContext &Context, // Perform template argument deduction for the template name. if (Sema::TemplateDeductionResult Result = DeduceTemplateArguments(Context, + TemplateParams, Param->getTemplateName(), TemplateName(SpecArg->getSpecializedTemplate()), Info, Deduced)) return Result; - // FIXME: Can the # of arguments in the parameter and the argument - // differ due to default arguments? unsigned NumArgs = Param->getNumArgs(); const TemplateArgumentList &ArgArgs = SpecArg->getTemplateArgs(); if (NumArgs != ArgArgs.size()) @@ -315,8 +354,8 @@ static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T, Qualifiers &Quals) { assert(T.isCanonical() && "Only operates on canonical types"); if (!isa<ArrayType>(T)) { - Quals = T.getQualifiers(); - return T.getUnqualifiedType(); + Quals = T.getLocalQualifiers(); + return T.getLocalUnqualifiedType(); } assert(!T.hasQualifiers() && "canonical array type has qualifiers!"); @@ -639,9 +678,9 @@ DeduceTemplateArguments(ASTContext &Context, // template-name<T> (where template-name refers to a class template) // template-name<i> - // TT<T> (TODO) - // TT<i> (TODO) - // TT<> (TODO) + // TT<T> + // TT<i> + // TT<> case Type::TemplateSpecialization: { const TemplateSpecializationType *SpecParam = cast<TemplateSpecializationType>(Param); @@ -785,13 +824,28 @@ DeduceTemplateArguments(ASTContext &Context, break; case TemplateArgument::Type: - assert(Arg.getKind() == TemplateArgument::Type && "Type/value mismatch"); - return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(), - Arg.getAsType(), Info, Deduced, 0); - + if (Arg.getKind() == TemplateArgument::Type) + return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(), + Arg.getAsType(), Info, Deduced, 0); + Info.FirstArg = Param; + Info.SecondArg = Arg; + return Sema::TDK_NonDeducedMismatch; + + case TemplateArgument::Template: + if (Arg.getKind() == TemplateArgument::Template) + return DeduceTemplateArguments(Context, TemplateParams, + Param.getAsTemplate(), + Arg.getAsTemplate(), Info, Deduced); + Info.FirstArg = Param; + Info.SecondArg = Arg; + return Sema::TDK_NonDeducedMismatch; + case TemplateArgument::Declaration: - // FIXME: Implement this check - assert(false && "Unimplemented template argument deduction case"); + if (Arg.getKind() == TemplateArgument::Declaration && + Param.getAsDecl()->getCanonicalDecl() == + Arg.getAsDecl()->getCanonicalDecl()) + return Sema::TDK_Success; + Info.FirstArg = Param; Info.SecondArg = Arg; return Sema::TDK_NonDeducedMismatch; @@ -829,7 +883,10 @@ DeduceTemplateArguments(ASTContext &Context, if (Arg.getKind() == TemplateArgument::Expression) return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsExpr(), Info, Deduced); - + if (Arg.getKind() == TemplateArgument::Declaration) + return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsDecl(), + Info, Deduced); + assert(false && "Type/value mismatch"); Info.FirstArg = Param; Info.SecondArg = Arg; @@ -885,13 +942,21 @@ static bool isSameTemplateArg(ASTContext &Context, return X.getAsDecl()->getCanonicalDecl() == Y.getAsDecl()->getCanonicalDecl(); + case TemplateArgument::Template: + return Context.getCanonicalTemplateName(X.getAsTemplate()) + .getAsVoidPointer() == + Context.getCanonicalTemplateName(Y.getAsTemplate()) + .getAsVoidPointer(); + case TemplateArgument::Integral: return *X.getAsIntegral() == *Y.getAsIntegral(); - case TemplateArgument::Expression: - // FIXME: We assume that all expressions are distinct, but we should - // really check their canonical forms. - return false; + case TemplateArgument::Expression: { + llvm::FoldingSetNodeID XID, YID; + X.getAsExpr()->Profile(XID, Context, true); + Y.getAsExpr()->Profile(YID, Context, true); + return XID == YID; + } case TemplateArgument::Pack: if (X.pack_size() != Y.pack_size()) @@ -1030,15 +1095,6 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, Info.FirstArg = Partial->getTemplateArgs()[I]; return TDK_SubstitutionFailure; } - } else if (TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(Param)) { - // FIXME: template template arguments should really resolve to decls - DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InstExpr); - if (!DRE || CheckTemplateArgument(TTP, DRE)) { - Info.Param = makeTemplateParameter(Param); - Info.FirstArg = Partial->getTemplateArgs()[I]; - return TDK_SubstitutionFailure; - } } } @@ -1384,16 +1440,16 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // - If A is a cv-qualified type, the top level cv-qualifiers of A’s // type are ignored for type deduction. QualType CanonArgType = Context.getCanonicalType(ArgType); - if (CanonArgType.getCVRQualifiers()) - ArgType = CanonArgType.getUnqualifiedType(); + if (CanonArgType.getLocalCVRQualifiers()) + ArgType = CanonArgType.getLocalUnqualifiedType(); } } // C++0x [temp.deduct.call]p3: // If P is a cv-qualified type, the top level cv-qualifiers of P’s type // are ignored for type deduction. - if (CanonParamType.getCVRQualifiers()) - ParamType = CanonParamType.getUnqualifiedType(); + if (CanonParamType.getLocalCVRQualifiers()) + ParamType = CanonParamType.getLocalUnqualifiedType(); if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) { // [...] If P is a reference type, the type referred to by P is used // for type deduction. @@ -2074,6 +2130,7 @@ Sema::getMoreSpecializedPartialSpecialization( 0); // Determine whether PS2 is at least as specialized as PS1 + Deduced.clear(); Deduced.resize(PS1->getTemplateParameters()->size()); bool Better2 = !DeduceTemplateArgumentsDuringPartialOrdering(Context, PS1->getTemplateParameters(), @@ -2153,6 +2210,9 @@ MarkUsedTemplateParameters(Sema &SemaRef, return; } + if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) + MarkUsedTemplateParameters(SemaRef, QTN->getQualifier(), OnlyDeduced, + Depth, Used); if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced, Depth, Used); @@ -2309,6 +2369,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, switch (TemplateArg.getKind()) { case TemplateArgument::Null: case TemplateArgument::Integral: + case TemplateArgument::Declaration: break; case TemplateArgument::Type: @@ -2316,12 +2377,9 @@ MarkUsedTemplateParameters(Sema &SemaRef, Depth, Used); break; - case TemplateArgument::Declaration: - if (TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(TemplateArg.getAsDecl())) { - if (TTP->getDepth() == Depth) - Used[TTP->getIndex()] = true; - } + case TemplateArgument::Template: + MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsTemplate(), + OnlyDeduced, Depth, Used); break; case TemplateArgument::Expression: diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index dfe37d8..58fe59e 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -28,11 +28,20 @@ using namespace clang; /// \brief Retrieve the template argument list(s) that should be used to /// instantiate the definition of the given declaration. +/// +/// \param D the declaration for which we are computing template instantiation +/// arguments. +/// +/// \param Innermost if non-NULL, the innermost template argument list. MultiLevelTemplateArgumentList -Sema::getTemplateInstantiationArgs(NamedDecl *D) { +Sema::getTemplateInstantiationArgs(NamedDecl *D, + const TemplateArgumentList *Innermost) { // Accumulate the set of template argument lists in this structure. MultiLevelTemplateArgumentList Result; + if (Innermost) + Result.addOuterTemplateArguments(Innermost); + DeclContext *Ctx = dyn_cast<DeclContext>(D); if (!Ctx) Ctx = D->getDeclContext(); @@ -87,6 +96,23 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D) { return Result; } +bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const { + switch (Kind) { + case TemplateInstantiation: + case DefaultTemplateArgumentInstantiation: + case DefaultFunctionArgumentInstantiation: + return true; + + case ExplicitTemplateArgumentSubstitution: + case DeducedTemplateArgumentSubstitution: + case PriorTemplateArgumentSubstitution: + case DefaultTemplateArgumentChecking: + return false; + } + + return true; +} + Sema::InstantiatingTemplate:: InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Decl *Entity, @@ -104,7 +130,6 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Inst.NumTemplateArgs = 0; Inst.InstantiationRange = InstantiationRange; SemaRef.ActiveTemplateInstantiations.push_back(Inst); - Invalid = false; } } @@ -128,7 +153,6 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, Inst.NumTemplateArgs = NumTemplateArgs; Inst.InstantiationRange = InstantiationRange; SemaRef.ActiveTemplateInstantiations.push_back(Inst); - Invalid = false; } } @@ -152,7 +176,9 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, Inst.NumTemplateArgs = NumTemplateArgs; Inst.InstantiationRange = InstantiationRange; SemaRef.ActiveTemplateInstantiations.push_back(Inst); - Invalid = false; + + if (!Inst.isInstantiationRecord()) + ++SemaRef.NonInstantiationEntries; } } @@ -164,48 +190,119 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, SourceRange InstantiationRange) : SemaRef(SemaRef) { - Invalid = CheckInstantiationDepth(PointOfInstantiation, - InstantiationRange); - if (!Invalid) { - ActiveTemplateInstantiation Inst; - Inst.Kind - = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution; - Inst.PointOfInstantiation = PointOfInstantiation; - Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec); - Inst.TemplateArgs = TemplateArgs; - Inst.NumTemplateArgs = NumTemplateArgs; - Inst.InstantiationRange = InstantiationRange; - SemaRef.ActiveTemplateInstantiations.push_back(Inst); - Invalid = false; - } + Invalid = false; + + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + + assert(!Inst.isInstantiationRecord()); + ++SemaRef.NonInstantiationEntries; } Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, - SourceLocation PointOfInstantation, + SourceLocation PointOfInstantiation, ParmVarDecl *Param, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, SourceRange InstantiationRange) : SemaRef(SemaRef) { - Invalid = CheckInstantiationDepth(PointOfInstantation, InstantiationRange); + Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange); if (!Invalid) { ActiveTemplateInstantiation Inst; Inst.Kind = ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation; - Inst.PointOfInstantiation = PointOfInstantation; + Inst.PointOfInstantiation = PointOfInstantiation; Inst.Entity = reinterpret_cast<uintptr_t>(Param); Inst.TemplateArgs = TemplateArgs; Inst.NumTemplateArgs = NumTemplateArgs; Inst.InstantiationRange = InstantiationRange; SemaRef.ActiveTemplateInstantiations.push_back(Inst); - Invalid = false; } } +Sema::InstantiatingTemplate:: +InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + NonTypeTemplateParmDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange) : SemaRef(SemaRef) { + Invalid = false; + + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Template = Template; + Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + + assert(!Inst.isInstantiationRecord()); + ++SemaRef.NonInstantiationEntries; +} + +Sema::InstantiatingTemplate:: +InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + TemplateTemplateParmDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange) : SemaRef(SemaRef) { + Invalid = false; + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Template = Template; + Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + + assert(!Inst.isInstantiationRecord()); + ++SemaRef.NonInstantiationEntries; +} + +Sema::InstantiatingTemplate:: +InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + NamedDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange) : SemaRef(SemaRef) { + Invalid = false; + + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentChecking; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Template = Template; + Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + + assert(!Inst.isInstantiationRecord()); + ++SemaRef.NonInstantiationEntries; +} + void Sema::InstantiatingTemplate::Clear() { if (!Invalid) { + if (!SemaRef.ActiveTemplateInstantiations.back().isInstantiationRecord()) { + assert(SemaRef.NonInstantiationEntries > 0); + --SemaRef.NonInstantiationEntries; + } + SemaRef.ActiveTemplateInstantiations.pop_back(); Invalid = true; } @@ -214,8 +311,11 @@ void Sema::InstantiatingTemplate::Clear() { bool Sema::InstantiatingTemplate::CheckInstantiationDepth( SourceLocation PointOfInstantiation, SourceRange InstantiationRange) { - if (SemaRef.ActiveTemplateInstantiations.size() - <= SemaRef.getLangOptions().InstantiationDepth) + assert(SemaRef.NonInstantiationEntries <= + SemaRef.ActiveTemplateInstantiations.size()); + if ((SemaRef.ActiveTemplateInstantiations.size() - + SemaRef.NonInstantiationEntries) + <= SemaRef.getLangOptions().InstantiationDepth) return false; SemaRef.Diag(PointOfInstantiation, @@ -322,6 +422,34 @@ void Sema::PrintInstantiationStack() { break; } + case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: { + NamedDecl *Parm = cast<NamedDecl>((Decl *)Active->Entity); + std::string Name; + if (!Parm->getName().empty()) + Name = std::string(" '") + Parm->getName().str() + "'"; + + Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), + diag::note_prior_template_arg_substitution) + << isa<TemplateTemplateParmDecl>(Parm) + << Name + << getTemplateArgumentBindingsText( + Active->Template->getTemplateParameters(), + Active->TemplateArgs, + Active->NumTemplateArgs) + << Active->InstantiationRange; + break; + } + + case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: { + Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), + diag::note_template_default_arg_checking) + << getTemplateArgumentBindingsText( + Active->Template->getTemplateParameters(), + Active->TemplateArgs, + Active->NumTemplateArgs) + << Active->InstantiationRange; + break; + } } } } @@ -332,18 +460,20 @@ bool Sema::isSFINAEContext() const { Active = ActiveTemplateInstantiations.rbegin(), ActiveEnd = ActiveTemplateInstantiations.rend(); Active != ActiveEnd; - ++Active) { - + ++Active) + { switch(Active->Kind) { case ActiveTemplateInstantiation::TemplateInstantiation: case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: - // This is a template instantiation, so there is no SFINAE. return false; case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: - // A default template argument instantiation may or may not be a - // SFINAE context; look further up the stack. + case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: + case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: + // A default template argument instantiation and substitution into + // template parameters with arguments for prior parameters may or may + // not be a SFINAE context; look further up the stack. break; case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: @@ -427,6 +557,9 @@ namespace { Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E, bool isAddressOfOperand); + Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E, + bool isAddressOfOperand); + /// \brief Transforms a template type parameter type by performing /// substitution of the corresponding template type argument. QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, @@ -440,10 +573,11 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) { if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { if (TTP->getDepth() < TemplateArgs.getNumLevels()) { - assert(TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsDecl() && + TemplateName Template + = TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsTemplate(); + assert(!Template.isNull() && Template.getAsTemplateDecl() && "Wrong kind of template template argument"); - return cast<TemplateDecl>(TemplateArgs(TTP->getDepth(), - TTP->getPosition()).getAsDecl()); + return Template.getAsTemplateDecl(); } // If the corresponding template argument is NULL or non-existent, it's @@ -454,9 +588,8 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) { TTP->getPosition())) return D; - // FIXME: Implement depth reduction of template template parameters - assert(false && - "Reducing depth of template template parameters is not yet implemented"); + // Fall through to find the instantiated declaration for this template + // template parameter. } return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D), TemplateArgs); @@ -567,7 +700,6 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, NamedDecl *D = E->getDecl(); if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { if (NTTP->getDepth() < TemplateArgs.getNumLevels()) { - // If the corresponding template argument is NULL or non-existent, it's // because we are performing instantiation from explicitly-specified // template arguments in a function template, but there were some @@ -592,7 +724,38 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, if (!VD) return SemaRef.ExprError(); - return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(), + if (VD->getDeclContext()->isRecord()) { + // If the value is a class member, we might have a pointer-to-member. + // Determine whether the non-type template template parameter is of + // pointer-to-member type. If so, we need to build an appropriate + // expression for a pointer-to-member, since a "normal" DeclRefExpr + // would refer to the member itself. + if (NTTP->getType()->isMemberPointerType()) { + QualType ClassType + = SemaRef.Context.getTypeDeclType( + cast<RecordDecl>(VD->getDeclContext())); + NestedNameSpecifier *Qualifier + = NestedNameSpecifier::Create(SemaRef.Context, 0, false, + ClassType.getTypePtr()); + CXXScopeSpec SS; + SS.setScopeRep(Qualifier); + OwningExprResult RefExpr + = SemaRef.BuildDeclRefExpr(VD, + VD->getType().getNonReferenceType(), + E->getLocation(), + /*FIXME:*/false, /*FIXME:*/false, + &SS); + if (RefExpr.isInvalid()) + return SemaRef.ExprError(); + + return SemaRef.CreateBuiltinUnaryOp(E->getLocation(), + UnaryOperator::AddrOf, + move(RefExpr)); + } + } + + return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), + E->getLocation(), /*FIXME:*/false, /*FIXME:*/false); } @@ -625,10 +788,46 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, if (!InstD) return SemaRef.ExprError(); - // If we instantiated an UnresolvedUsingDecl and got back an UsingDecl, - // we need to get the underlying decl. - // FIXME: Is this correct? Maybe FindInstantiatedDecl should do this? - InstD = InstD->getUnderlyingDecl(); + // 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(); + } + } CXXScopeSpec SS; NestedNameSpecifier *Qualifier = 0; @@ -648,6 +847,15 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, isAddressOfOperand); } +Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr( + CXXDefaultArgExpr *E, bool isAddressOfOperand) { + assert(!cast<FunctionDecl>(E->getParam()->getDeclContext())-> + getDescribedFunctionTemplate() && + "Default arg expressions are never formed in dependent cases."); + return SemaRef.Owned(E->Retain()); +} + + QualType TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, TemplateTypeParmTypeLoc TL) { @@ -889,9 +1097,9 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, Member != MemberEnd; ++Member) { Decl *NewMember = SubstDecl(*Member, Instantiation, TemplateArgs); if (NewMember) { - if (NewMember->isInvalidDecl()) + if (NewMember->isInvalidDecl()) { Invalid = true; - else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) + } else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) Fields.push_back(DeclPtrTy::make(Field)); else if (UsingDecl *UD = dyn_cast<UsingDecl>(NewMember)) Instantiation->addDecl(UD); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 7288ae2..7e618cd 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===/ #include "Sema.h" +#include "Lookup.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" @@ -28,6 +29,8 @@ namespace { DeclContext *Owner; const MultiLevelTemplateArgumentList &TemplateArgs; + void InstantiateAttrs(Decl *Tmpl, Decl *New); + public: typedef Sema::OwningExprResult OwningExprResult; @@ -62,11 +65,19 @@ namespace { Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D); Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); - Decl *VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D); + Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); + Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D); + Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); + Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); // Base case. FIXME: Remove once we can instantiate everything. - Decl *VisitDecl(Decl *) { - assert(false && "Template instantiation of unknown declaration kind!"); + Decl *VisitDecl(Decl *D) { + unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID( + Diagnostic::Error, + "cannot instantiate %0 yet"); + SemaRef.Diag(D->getLocation(), DiagID) + << D->getDeclKindName(); + return 0; } @@ -89,6 +100,18 @@ namespace { }; } +// FIXME: Is this too simple? +void TemplateDeclInstantiator::InstantiateAttrs(Decl *Tmpl, Decl *New) { + for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr; + TmplAttr = TmplAttr->getNext()) { + + // FIXME: Is cloning correct for all attributes? + Attr *NewAttr = TmplAttr->clone(SemaRef.Context); + + New->addAttr(NewAttr); + } +} + Decl * TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) { assert(false && "Translation units cannot be instantiated"); @@ -172,6 +195,15 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { = SemaRef.SubstExpr(D->getInit(), TemplateArgs); if (Init.isInvalid()) Var->setInvalidDecl(); + else if (!D->getType()->isDependentType() && + !D->getInit()->isTypeDependent() && + !D->getInit()->isValueDependent()) { + // If neither the declaration's type nor its initializer are dependent, + // 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->setInit(SemaRef.Context, Init.takeAs<Expr>()); + } else if (ParenListExpr *PLE = dyn_cast<ParenListExpr>((Expr *)Init.get())) { // FIXME: We're faking all of the comma locations, which is suboptimal. // Do we even need these comma locations? @@ -258,6 +290,8 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { return 0; } + InstantiateAttrs(D, Field); + if (Invalid) Field->setInvalidDecl(); @@ -632,6 +666,12 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { TemplateParams, Function); Function->setDescribedFunctionTemplate(FunctionTemplate); FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext()); + } else if (FunctionTemplate) { + // Record this function template specialization. + Function->setFunctionTemplateSpecialization(SemaRef.Context, + FunctionTemplate, + &TemplateArgs.getInnermost(), + InsertPos); } if (InitFunctionInstantiation(Function, D)) @@ -645,9 +685,10 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { // Look only into the namespace where the friend would be declared to // find a previous declaration. This is the innermost enclosing namespace, // as described in ActOnFriendFunctionDecl. - Sema::LookupResult R; - SemaRef.LookupQualifiedName(R, DC, Function->getDeclName(), - Sema::LookupOrdinaryName, true); + LookupResult R(SemaRef, Function->getDeclName(), SourceLocation(), + Sema::LookupOrdinaryName, + Sema::ForRedeclaration); + SemaRef.LookupQualifiedName(R, DC); PrevDecl = R.getAsSingleDecl(SemaRef.Context); @@ -683,14 +724,6 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); } - if (FunctionTemplate && !TemplateParams) { - // Record this function template specialization. - Function->setFunctionTemplateSpecialization(SemaRef.Context, - FunctionTemplate, - &TemplateArgs.getInnermost(), - InsertPos); - } - return Function; } @@ -785,9 +818,17 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, if (D->isOutOfLine()) FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext()); Method->setDescribedFunctionTemplate(FunctionTemplate); - } else if (!FunctionTemplate) + } else if (FunctionTemplate) { + // Record this function template specialization. + Method->setFunctionTemplateSpecialization(SemaRef.Context, + FunctionTemplate, + &TemplateArgs.getInnermost(), + InsertPos); + } else { + // Record that this is an instantiation of a member function. Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); - + } + // If we are instantiating a member function defined // out-of-line, the instantiation will have the same lexical // context (which will be a namespace scope) as the template. @@ -805,8 +846,10 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, NamedDecl *PrevDecl = 0; if (!FunctionTemplate || TemplateParams) { - Sema::LookupResult R; - SemaRef.LookupQualifiedName(R, Owner, Name, Sema::LookupOrdinaryName, true); + LookupResult R(SemaRef, Name, SourceLocation(), + Sema::LookupOrdinaryName, + Sema::ForRedeclaration); + SemaRef.LookupQualifiedName(R, Owner); PrevDecl = R.getAsSingleDecl(SemaRef.Context); // In C++, the previous declaration we find might be a tag type @@ -817,13 +860,6 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, PrevDecl = 0; } - if (FunctionTemplate && !TemplateParams) - // Record this function template specialization. - Method->setFunctionTemplateSpecialization(SemaRef.Context, - FunctionTemplate, - &TemplateArgs.getInnermost(), - InsertPos); - bool Redeclaration = false; bool OverloadableAttrRequired = false; SemaRef.CheckFunctionDeclaration(Method, PrevDecl, false, Redeclaration, @@ -898,18 +934,8 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( D->wasDeclaredWithTypename(), D->isParameterPack()); - // FIXME: Do we actually want to perform substitution here? I don't think - // we do. - if (D->hasDefaultArgument()) { - DeclaratorInfo *DefaultPattern = D->getDefaultArgumentInfo(); - DeclaratorInfo *DefaultInst - = SemaRef.SubstType(DefaultPattern, TemplateArgs, - D->getDefaultArgumentLoc(), - D->getDeclName()); - - Inst->setDefaultArgument(DefaultInst, - D->defaultArgumentWasInherited() /* preserve? */); - } + if (D->hasDefaultArgument()) + Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false); // Introduce this template parameter's instantiation into the instantiation // scope. @@ -959,7 +985,75 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( } Decl * -TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) { +TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( + TemplateTemplateParmDecl *D) { + // Instantiate the template parameter list of the template template parameter. + TemplateParameterList *TempParams = D->getTemplateParameters(); + TemplateParameterList *InstParams; + { + // Perform the actual substitution of template parameters within a new, + // local instantiation scope. + Sema::LocalInstantiationScope Scope(SemaRef); + InstParams = SubstTemplateParams(TempParams); + if (!InstParams) + return NULL; + } + + // Build the template template parameter. + TemplateTemplateParmDecl *Param + = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getDepth() - 1, D->getPosition(), + D->getIdentifier(), InstParams); + Param->setDefaultArgument(D->getDefaultArgument()); + + // Introduce this template parameter's instantiation into the instantiation + // scope. + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param); + + return Param; +} + +Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { + // Using directives are never dependent, so they require no explicit + + UsingDirectiveDecl *Inst + = UsingDirectiveDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getNamespaceKeyLocation(), + D->getQualifierRange(), D->getQualifier(), + D->getIdentLocation(), + D->getNominatedNamespace(), + D->getCommonAncestor()); + Owner->addDecl(Inst); + return Inst; +} + +Decl * TemplateDeclInstantiator + ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { + NestedNameSpecifier *NNS = + SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(), + D->getTargetNestedNameRange(), + TemplateArgs); + if (!NNS) + return 0; + + CXXScopeSpec SS; + SS.setRange(D->getTargetNestedNameRange()); + SS.setScopeRep(NNS); + + NamedDecl *UD = + SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(), + D->getUsingLoc(), SS, D->getLocation(), + D->getDeclName(), 0, + /*instantiation*/ true, + /*typename*/ true, D->getTypenameLoc()); + if (UD) + SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD), + D); + return UD; +} + +Decl * TemplateDeclInstantiator + ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { NestedNameSpecifier *NNS = SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(), D->getTargetNestedNameRange(), @@ -972,9 +1066,11 @@ TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) { SS.setScopeRep(NNS); NamedDecl *UD = - SemaRef.BuildUsingDeclaration(D->getLocation(), SS, - D->getTargetNameLocation(), - D->getTargetName(), 0, D->isTypeName()); + SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(), + D->getUsingLoc(), SS, D->getLocation(), + D->getDeclName(), 0, + /*instantiation*/ true, + /*typename*/ false, SourceLocation()); if (UD) SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD), D); @@ -1006,7 +1102,7 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) { PI != PE; ++PI) { NamedDecl *D = cast_or_null<NamedDecl>(Visit(*PI)); Params.push_back(D); - Invalid = Invalid || !D; + Invalid = Invalid || !D || D->isInvalidDecl(); } // Clean up if we had an error. @@ -1240,6 +1336,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, (void) FunTmpl; ActiveInst.Kind = ActiveInstType::TemplateInstantiation; ActiveInst.Entity = reinterpret_cast<uintptr_t>(New); + --SemaRef.NonInstantiationEntries; } } @@ -1656,7 +1753,13 @@ static bool isInstantiationOf(EnumDecl *Pattern, return false; } -static bool isInstantiationOf(UnresolvedUsingDecl *Pattern, +static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern, + UsingDecl *Instance, + ASTContext &C) { + return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern; +} + +static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern, UsingDecl *Instance, ASTContext &C) { return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern; @@ -1679,7 +1782,15 @@ static bool isInstantiationOfStaticDataMember(VarDecl *Pattern, static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) { if (D->getKind() != Other->getKind()) { - if (UnresolvedUsingDecl *UUD = dyn_cast<UnresolvedUsingDecl>(D)) { + if (UnresolvedUsingTypenameDecl *UUD + = dyn_cast<UnresolvedUsingTypenameDecl>(D)) { + if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) { + return isInstantiationOf(UUD, UD, Ctx); + } + } + + if (UnresolvedUsingValueDecl *UUD + = dyn_cast<UnresolvedUsingValueDecl>(D)) { if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) { return isInstantiationOf(UUD, UD, Ctx); } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index f003127..00dc809 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -229,7 +229,8 @@ static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){ case DeclSpec::TST_enum: case DeclSpec::TST_union: case DeclSpec::TST_struct: { - TypeDecl *D = cast_or_null<TypeDecl>(static_cast<Decl *>(DS.getTypeRep())); + TypeDecl *D + = dyn_cast_or_null<TypeDecl>(static_cast<Decl *>(DS.getTypeRep())); if (!D) { // This can happen in C++ with ambiguous lookups. Result = Context.IntTy; @@ -1703,7 +1704,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, // class template specialization, or an array with known size of such, // try to instantiate it. QualType MaybeTemplate = T; - if (const ConstantArrayType *Array = T->getAs<ConstantArrayType>()) + if (const ConstantArrayType *Array = Context.getAsConstantArrayType(T)) MaybeTemplate = Array->getElementType(); if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) { if (ClassTemplateSpecializationDecl *ClassTemplateSpec diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 767725a..2bee32a 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1063,8 +1063,18 @@ public: /// Subclasses may override this routine to provide different behavior. OwningExprResult RebuildInitList(SourceLocation LBraceLoc, MultiExprArg Inits, - SourceLocation RBraceLoc) { - return SemaRef.ActOnInitList(LBraceLoc, move(Inits), RBraceLoc); + SourceLocation RBraceLoc, + QualType ResultTy) { + OwningExprResult Result + = SemaRef.ActOnInitList(LBraceLoc, move(Inits), RBraceLoc); + if (Result.isInvalid() || ResultTy->isDependentType()) + return move(Result); + + // Patch in the result type we were given, which may have been computed + // when the initial InitListExpr was built. + InitListExpr *ILE = cast<InitListExpr>((Expr *)Result.get()); + ILE->setType(ResultTy); + return move(Result); } /// \brief Build a new designated initializer expression. @@ -1699,7 +1709,7 @@ Sema::OwningStmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) { if (E.isInvalid()) return getSema().StmtError(); - return getSema().Owned(E.takeAs<Stmt>()); + return getSema().ActOnExprStmt(getSema().FullExpr(E)); } } @@ -1947,6 +1957,10 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc( break; + case TemplateArgument::Template: + Output = TemplateArgumentLoc(Arg, SourceRange(), Loc); + break; + case TemplateArgument::Expression: Output = TemplateArgumentLoc(Arg, Arg.getAsExpr()); break; @@ -1987,7 +2001,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument( DeclarationName Name; if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) Name = ND->getDeclName(); - TemporaryBase Rebase(*this, SourceLocation(), Name); + TemporaryBase Rebase(*this, Input.getLocation(), Name); Decl *D = getDerived().TransformDecl(Arg.getAsDecl()); if (!D) return true; @@ -2008,6 +2022,19 @@ bool TreeTransform<Derived>::TransformTemplateArgument( return false; } + case TemplateArgument::Template: { + TemporaryBase Rebase(*this, Input.getLocation(), DeclarationName()); + TemplateName Template + = getDerived().TransformTemplateName(Arg.getAsTemplate()); + if (Template.isNull()) + return true; + + Output = TemplateArgumentLoc(TemplateArgument(Template), + Input.getTemplateQualifierRange(), + Input.getTemplateNameLoc()); + return false; + } + case TemplateArgument::Expression: { // Template argument expressions are not potentially evaluated. EnterExpressionEvaluationContext Unevaluated(getSema(), @@ -2119,7 +2146,7 @@ template<typename Derived> QualType TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, QualifiedTypeLoc T) { - Qualifiers Quals = T.getType().getQualifiers(); + Qualifiers Quals = T.getType().getLocalQualifiers(); QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc()); if (Result.isNull()) @@ -3893,7 +3920,7 @@ TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E, return SemaRef.Owned(E->Retain()); return getDerived().RebuildInitList(E->getLBraceLoc(), move_arg(Inits), - E->getRBraceLoc()); + E->getRBraceLoc(), E->getType()); } template<typename Derived> @@ -5279,7 +5306,7 @@ TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, QualType T) { if (T->isDependentType() || T->isRecordType() || (SemaRef.getLangOptions().CPlusPlus0x && T->isEnumeralType())) { - assert(!T.hasQualifiers() && "Can't get cv-qualifiers here"); + assert(!T.hasLocalQualifiers() && "Can't get cv-qualifiers here"); return NestedNameSpecifier::Create(SemaRef.Context, Prefix, TemplateKW, T.getTypePtr()); } @@ -5363,6 +5390,9 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, return getSema().CreateBuiltinArraySubscriptExpr(move(First), DRE->getLocStart(), move(Second), OpLoc); + } else if (Op == OO_Arrow) { + // -> is never a builtin operation. + return SemaRef.BuildOverloadedArrowExpr(0, move(First), OpLoc); } else if (SecondExpr == 0 || isPostIncDec) { if (!FirstExpr->getType()->isOverloadableType()) { // The argument is not of overloadable type, so try to create a |