From: Douglas Gregor Date: Wed, 4 Feb 2009 17:27:36 +0000 (+0000) Subject: Some name-lookup-related fixes, from Piotr Rak! X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=47b9a1ca55e61e37f5a368740e29de190345acc6;p=clang Some name-lookup-related fixes, from Piotr Rak! - Changes Lookup*Name functions to return NamedDecls, instead of Decls. Unfortunately my recent statement that it will simplify lot of code, was not quite right, but it simplifies some... - Makes MergeLookupResult SmallPtrSet instead of vector, following Douglas suggestions. - Adds %qN format for printing qualified names to Diagnostic. - Avoids searching for using-directives in Scopes, which are not DeclScope, during unqualified name lookup. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63739 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/InternalsManual.html b/docs/InternalsManual.html index f35dcc2de9..0d029f7e37 100644 --- a/docs/InternalsManual.html +++ b/docs/InternalsManual.html @@ -321,6 +321,11 @@ Clang:

DeclarationName corresponds to an Objective-C instance method selector. As such, it prints the selector with a leading '-'.

+"q" format +Example:"candidate found by name lookup is %q0" +Class:NamedDecl* +Description

This formatter indicates that the fully-qualified name of the declaration should be printed, e.g., "std::vector" rather than "vector".

+

It is really easy to add format specifiers to the Clang diagnostics system, diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 5305413300..b3ec04936d 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -99,6 +99,14 @@ public: /// For simple declarations, getNameAsCString() should suffice. std::string getNameAsString() const { return Name.getAsString(); } + /// getQualifiedNameAsString - Returns human-readable qualified name for + /// declaration, like A::B::i, for i being member of namespace A::B. + /// If declaration is not member of context which can be named (record, + /// namespace), it will return same result as getNameAsString(). + /// Creating this name is expensive, so it should be called only when + /// performance doesn't matter. + std::string getQualifiedNameAsString() const; + /// declarationReplaces - Determine whether this declaration, if /// known to be well-formed within its context, will replace the /// declaration OldD if introduced into scope. A declaration will @@ -1134,6 +1142,14 @@ protected: friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C); }; +/// Insertion operator for diagnostics. This allows sending NamedDecl's +/// into a diagnostic with <<. +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + NamedDecl* ND) { + DB.AddTaggedVal(reinterpret_cast(ND), Diagnostic::ak_nameddecl); + return DB; +} + } // end namespace clang #endif diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 2f3184c46b..63dbdd6265 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -77,13 +77,14 @@ public: }; enum ArgumentKind { - ak_std_string, // std::string - ak_c_string, // const char * - ak_sint, // int - ak_uint, // unsigned - ak_identifierinfo, // IdentifierInfo - ak_qualtype, // QualType - ak_declarationname // DeclarationName + ak_std_string, // std::string + ak_c_string, // const char * + ak_sint, // int + ak_uint, // unsigned + ak_identifierinfo, // IdentifierInfo + ak_qualtype, // QualType + ak_declarationname, // DeclarationName + ak_nameddecl // NamedDecl * }; private: diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def index 54f5086a53..c3e33965cf 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.def +++ b/include/clang/Basic/DiagnosticSemaKinds.def @@ -1044,7 +1044,7 @@ DIAG(note_ambiguous_member_found, NOTE, DIAG(err_ambiguous_reference, ERROR, "reference to %0 is ambiguous") DIAG(note_ambiguous_candidate, NOTE, - "candidate found by name lookup is '%0'") + "candidate found by name lookup is %q0") // C++ operator overloading DIAG(err_operator_overload_needs_class_or_enum, ERROR, diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 6bc02e0a97..b95ff3e180 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -17,6 +17,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/Expr.h" #include "clang/Basic/IdentifierTable.h" +#include using namespace clang; @@ -144,6 +145,41 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, // NamedDecl Implementation //===----------------------------------------------------------------------===// +std::string NamedDecl::getQualifiedNameAsString() const { + std::vector Names; + std::string QualName; + const DeclContext *Ctx = getDeclContext(); + + if (Ctx->isFunctionOrMethod()) + return getNameAsString(); + + while (Ctx) { + if (Ctx->isFunctionOrMethod()) + // FIXME: That probably will happen, when D was member of local + // scope class/struct/union. How do we handle this case? + break; + + if (const NamedDecl *ND = dyn_cast(Ctx)) + Names.push_back(ND->getNameAsString()); + else + break; + + Ctx = Ctx->getParent(); + } + + std::vector::reverse_iterator + I = Names.rbegin(), + End = Names.rend(); + + for (; I!=End; ++I) + QualName += *I + "::"; + + QualName += getNameAsString(); + + return QualName; +} + + bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch"); diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp index 5b1145f70b..2429bddfeb 100644 --- a/lib/Basic/Diagnostic.cpp +++ b/lib/Basic/Diagnostic.cpp @@ -608,6 +608,7 @@ FormatDiagnostic(llvm::SmallVectorImpl &OutStr) const { } case Diagnostic::ak_qualtype: case Diagnostic::ak_declarationname: + case Diagnostic::ak_nameddecl: OutStr.push_back('\''); getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo), Modifier, ModifierLen, diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 6041736242..03a6b3c98a 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -36,8 +36,7 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val, assert(ModLen == 0 && ArgLen == 0 && "Invalid modifier for QualType argument"); - } else { - assert(Kind == Diagnostic::ak_declarationname); + } else if (Kind == Diagnostic::ak_declarationname) { DeclarationName N = DeclarationName::getFromOpaqueInteger(Val); S = N.getAsString(); @@ -49,6 +48,13 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val, else assert(ModLen == 0 && ArgLen == 0 && "Invalid modifier for DeclarationName argument"); + } else { + assert(Kind == Diagnostic::ak_nameddecl); + assert(ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0 && + "Invalid modifier for NamedDecl* argument"); + + S = reinterpret_cast(Val)->getQualifiedNameAsString(); + } Output.append(S.begin(), S.end()); } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 9810ba0cb5..b0e24f5d14 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -607,7 +607,7 @@ public: /// results occurred for a given lookup. /// /// Any non-ambiguous lookup can be converted into a single - /// (possibly NULL) @c Decl* via a conversion function or the + /// (possibly NULL) @c NamedDecl* via a conversion function or the /// getAsDecl() method. This conversion permits the common-case /// usage in C and Objective-C where name lookup will always return /// a single declaration. @@ -615,7 +615,7 @@ public: /// The kind of entity that is actually stored within the /// LookupResult object. enum { - /// First is a single declaration (a Decl*), which may be NULL. + /// First is a single declaration (a NamedDecl*), which may be NULL. SingleDecl, /// First is a single declaration (an OverloadedFunctionDecl*). @@ -643,8 +643,9 @@ public: } StoredKind; /// The first lookup result, whose contents depend on the kind of - /// lookup result. This may be a Decl* (if StoredKind == - /// SingleDecl), the opaque pointer from an + /// lookup result. This may be a NamedDecl* (if StoredKind == + /// SingleDecl), OverloadedFunctionDecl* (if StoredKind == + /// OverloadedDeclSingleDecl), the opaque pointer from an /// IdentifierResolver::iterator (if StoredKind == /// OverloadedDeclFromIdResolver), a DeclContext::lookup_iterator /// (if StoredKind == OverloadedDeclFromDeclContext), or a @@ -721,7 +722,7 @@ public: AmbiguousReference }; - static LookupResult CreateLookupResult(ASTContext &Context, Decl *D); + static LookupResult CreateLookupResult(ASTContext &Context, NamedDecl *D); static LookupResult CreateLookupResult(ASTContext &Context, IdentifierResolver::iterator F, @@ -744,7 +745,7 @@ public: template static LookupResult CreateLookupResult(ASTContext &Context, Iterator B, std::size_t Len) { - Decl ** Array = new Decl*[Len]; + NamedDecl ** Array = new NamedDecl*[Len]; for (std::size_t Idx = 0; Idx < Len; ++Idx, ++B) Array[Idx] = *B; LookupResult Result; @@ -768,9 +769,9 @@ public: /// @brief Allows conversion of a lookup result into a /// declaration, with the same behavior as getAsDecl. - operator Decl*() const { return getAsDecl(); } + operator NamedDecl*() const { return getAsDecl(); } - Decl* getAsDecl() const; + NamedDecl* getAsDecl() const; BasePaths *getBasePaths() const; @@ -788,9 +789,9 @@ public: mutable uintptr_t Current; public: - typedef Decl * value_type; - typedef Decl * reference; - typedef Decl * pointer; + typedef NamedDecl * value_type; + typedef NamedDecl * reference; + typedef NamedDecl * pointer; typedef std::ptrdiff_t difference_type; typedef std::forward_iterator_tag iterator_category; diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index c77325f42d..8a257f78c1 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -36,7 +36,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, SourceLocation IdLoc, SourceLocation CCLoc, IdentifierInfo &II) { - Decl *SD = LookupParsedName(S, &SS, &II, LookupNestedNameSpecifierName); + NamedDecl *SD = LookupParsedName(S, &SS, &II, LookupNestedNameSpecifierName); if (SD) { if (TypedefDecl *TD = dyn_cast(SD)) { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index fbf4be79eb..a3ca97b5cb 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -207,7 +207,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) { // The third "scope" argument is 0 since we aren't enabling lazy built-in // creation from this context. - Decl *IDecl = LookupName(TUScope, Id, LookupOrdinaryName); + NamedDecl *IDecl = LookupName(TUScope, Id, LookupOrdinaryName); return dyn_cast_or_null(IDecl); } @@ -249,7 +249,7 @@ void Sema::InitBuiltinVaListType() { return; IdentifierInfo *VaIdent = &Context.Idents.get("__builtin_va_list"); - Decl *VaDecl = LookupName(TUScope, VaIdent, LookupOrdinaryName); + NamedDecl *VaDecl = LookupName(TUScope, VaIdent, LookupOrdinaryName); TypedefDecl *VaTypedef = cast(VaDecl); Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef)); } @@ -741,8 +741,8 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, FEnd = AnonRecord->field_end(); F != FEnd; ++F) { if ((*F)->getDeclName()) { - Decl *PrevDecl = LookupQualifiedName(Owner, (*F)->getDeclName(), - LookupOrdinaryName, true); + NamedDecl *PrevDecl = LookupQualifiedName(Owner, (*F)->getDeclName(), + LookupOrdinaryName, true); if (PrevDecl && !isa(PrevDecl)) { // C++ [class.union]p2: // The names of the members of an anonymous union shall be @@ -1174,7 +1174,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl, S = S->getParent(); DeclContext *DC; - Decl *PrevDecl; + NamedDecl *PrevDecl; NamedDecl *New; bool InvalidDecl = false; @@ -2523,7 +2523,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // among each other. Here they can only shadow globals, which is ok. IdentifierInfo *II = D.getIdentifier(); if (II) { - if (Decl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) { + if (NamedDecl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) { if (PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); @@ -2798,7 +2798,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, DeclContext *SearchDC = CurContext; DeclContext *DC = CurContext; - Decl *PrevDecl = 0; + NamedDecl *PrevDecl = 0; bool Invalid = false; @@ -2843,7 +2843,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, Invalid = true; } else - PrevDecl = dyn_cast_or_null(static_cast(R)); + PrevDecl = R; if (!getLangOptions().CPlusPlus && TK != TK_Reference) { // FIXME: This makes sure that we ignore the contexts associated @@ -3217,7 +3217,7 @@ Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD, DeclSpec::SCS_mutable); if (II) { - Decl *PrevDecl = LookupName(S, II, LookupMemberName, true); + NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true); if (PrevDecl && isDeclInScope(PrevDecl, CurContext, S) && !isa(PrevDecl)) { Diag(Loc, diag::err_duplicate_member) << II; @@ -3309,7 +3309,7 @@ Sema::DeclTy *Sema::ActOnIvar(Scope *S, (Expr *)BitfieldWidth); if (II) { - Decl *PrevDecl = LookupName(S, II, LookupMemberName, true); + NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true); if (PrevDecl && isDeclInScope(PrevDecl, CurContext, S) && !isa(PrevDecl)) { Diag(Loc, diag::err_duplicate_member) << II; @@ -3485,7 +3485,7 @@ Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl, // Verify that there isn't already something declared with this name in this // scope. - Decl *PrevDecl = LookupName(S, Id, LookupOrdinaryName); + NamedDecl *PrevDecl = LookupName(S, Id, LookupOrdinaryName); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(IdLoc, PrevDecl); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 33985ee1a3..231efc7563 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -865,8 +865,8 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { } // Look up the function - Decl *CleanupDecl = S.LookupName(S.TUScope, Attr.getParameterName(), - Sema::LookupOrdinaryName); + NamedDecl *CleanupDecl = S.LookupName(S.TUScope, Attr.getParameterName(), + Sema::LookupOrdinaryName); if (!CleanupDecl) { S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_found) << Attr.getParameterName(); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 2175ad3b93..5595215d55 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1375,8 +1375,8 @@ Sema::DeclTy *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // original-namespace-definition is the name of the namespace. Subsequently // in that declarative region, it is treated as an original-namespace-name. - Decl *PrevDecl = LookupName(DeclRegionScope, II, LookupOrdinaryName, - true); + NamedDecl *PrevDecl = LookupName(DeclRegionScope, II, LookupOrdinaryName, + true); if (NamespaceDecl *OrigNS = dyn_cast_or_null(PrevDecl)) { // This is an extended namespace definition. @@ -1444,7 +1444,7 @@ Sema::DeclTy *Sema::ActOnUsingDirective(Scope *S, DiagnoseAmbiguousLookup(R, NamespcName, IdentLoc); return 0; } - if (Decl *NS = R) { + if (NamedDecl *NS = R) { assert(isa(NS) && "expected namespace decl"); // C++ [namespace.udir]p1: // A using-directive specifies that the names in the nominated @@ -2230,7 +2230,7 @@ Sema::DeclTy *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) // FIXME: Need to check for abstract classes. IdentifierInfo *II = D.getIdentifier(); - if (Decl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) { + if (NamedDecl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) { // The scope should be freshly made just for us. There is just no way // it contains any previous declaration. assert(!S->isDeclScope(PrevDecl)); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 7c76f16275..1e87a6f819 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -64,7 +64,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, assert(ClassName && "Missing class identifier"); // Check for another declaration kind with the same name. - Decl *PrevDecl = LookupName(TUScope, ClassName, LookupOrdinaryName); + NamedDecl *PrevDecl = LookupName(TUScope, ClassName, LookupOrdinaryName); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(ClassLoc, PrevDecl); @@ -164,7 +164,7 @@ Sema::DeclTy *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, IdentifierInfo *ClassName, SourceLocation ClassLocation) { // Look for previous declaration of alias name - Decl *ADecl = LookupName(TUScope, AliasName, LookupOrdinaryName); + NamedDecl *ADecl = LookupName(TUScope, AliasName, LookupOrdinaryName); if (ADecl) { if (isa(ADecl)) Diag(AliasLocation, diag::warn_previous_alias_decl); @@ -174,7 +174,7 @@ Sema::DeclTy *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, return 0; } // Check for class declaration - Decl *CDeclU = LookupName(TUScope, ClassName, LookupOrdinaryName); + NamedDecl *CDeclU = LookupName(TUScope, ClassName, LookupOrdinaryName); if (const TypedefDecl *TDecl = dyn_cast_or_null(CDeclU)) { QualType T = TDecl->getUnderlyingType(); if (T->isObjCInterfaceType()) { @@ -550,7 +550,7 @@ Sema::DeclTy *Sema::ActOnStartClassImplementation( SourceLocation SuperClassLoc) { ObjCInterfaceDecl* IDecl = 0; // Check for another declaration kind with the same name. - Decl *PrevDecl = LookupName(TUScope, ClassName, LookupOrdinaryName); + NamedDecl *PrevDecl = LookupName(TUScope, ClassName, LookupOrdinaryName); if (PrevDecl && !isa(PrevDecl)) { Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; Diag(PrevDecl->getLocation(), diag::note_previous_definition); @@ -924,7 +924,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, for (unsigned i = 0; i != NumElts; ++i) { // Check for another declaration kind with the same name. - Decl *PrevDecl = LookupName(TUScope, IdentList[i], LookupOrdinaryName); + NamedDecl *PrevDecl = LookupName(TUScope, IdentList[i], LookupOrdinaryName); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(AtClassLoc, PrevDecl); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d408defbff..0c755f6d1f 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -563,7 +563,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, Loc)); } - Decl *D = 0; + NamedDecl *D = 0; if (Lookup.isAmbiguous()) { DiagnoseAmbiguousLookup(Lookup, Name, Loc, SS && SS->isSet() ? SS->getRange() @@ -627,9 +627,8 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // implicit member ref, because we want a pointer to the member in general, // not any specific instance's member. if (isAddressOfOperand && SS && !SS->isEmpty() && !HasTrailingLParen) { - NamedDecl *ND = dyn_cast(D); DeclContext *DC = static_cast(SS->getScopeRep()); - if (ND && isa(DC)) { + if (D && isa(DC)) { QualType DType; if (FieldDecl *FD = dyn_cast(D)) { DType = FD->getType().getNonReferenceType(); @@ -653,7 +652,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, } } } - return Owned(BuildDeclRefExpr(ND, DType, Loc, Dependent, Dependent,SS)); + return Owned(BuildDeclRefExpr(D, DType, Loc, Dependent, Dependent, SS)); } } } @@ -714,7 +713,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // Build the implicit member access expression. Expr *This = new (Context) CXXThisExpr(SourceLocation(), MD->getThisType(Context)); - return Owned(new (Context) MemberExpr(This, true, cast(D), + return Owned(new (Context) MemberExpr(This, true, D, SourceLocation(), MemberType)); } } @@ -1559,7 +1558,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, = LookupQualifiedName(RDecl, DeclarationName(&Member), LookupMemberName, false); - Decl *MemberDecl = 0; + NamedDecl *MemberDecl = 0; if (!Result) return ExprError(Diag(MemberLoc, diag::err_typecheck_no_member) << &Member << BaseExpr->getSourceRange()); diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index f893f1eec5..983231ccf4 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -52,7 +52,7 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, // Initialize the constant string interface lazily. This assumes // the NSConstantString interface is seen in this translation unit. IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString"); - Decl *IFace = LookupName(TUScope, NSIdent, LookupOrdinaryName); + NamedDecl *IFace = LookupName(TUScope, NSIdent, LookupOrdinaryName); ObjCInterfaceDecl *strIFace = dyn_cast_or_null(IFace); if (strIFace) Context.setObjCConstantStringInterface(strIFace); @@ -209,7 +209,7 @@ Sema::ExprResult Sema::ActOnClassMessage( } else { // 'super' has been used outside a method context. If a variable named // 'super' has been declared, redirect. If not, produce a diagnostic. - Decl *SuperDecl = LookupName(S, receiverName, LookupOrdinaryName); + NamedDecl *SuperDecl = LookupName(S, receiverName, LookupOrdinaryName); ValueDecl *VD = dyn_cast_or_null(SuperDecl); if (VD) { ExprResult ReceiverExpr = new DeclRefExpr(VD, VD->getType(), @@ -234,7 +234,7 @@ Sema::ExprResult Sema::ActOnClassMessage( // // If necessary, the following lookup could move to getObjCInterfaceDecl(). if (!ClassDecl) { - Decl *IDecl = LookupName(TUScope, receiverName, LookupOrdinaryName); + NamedDecl *IDecl = LookupName(TUScope, receiverName, LookupOrdinaryName); if (TypedefDecl *OCTD = dyn_cast_or_null(IDecl)) { const ObjCInterfaceType *OCIT; OCIT = OCTD->getUnderlyingType()->getAsObjCInterfaceType(); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 4cdd4abab3..65dd9490d2 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -114,7 +114,7 @@ static void AddScopeUsingDirectives(Scope *S, UsingDirectivesTy &UDirs) { /// ambiguity and overloaded functions without needing to create a /// Decl node. template -static Decl * +static NamedDecl * MaybeConstructOverloadSet(ASTContext &Context, DeclIterator I, DeclIterator IEnd) { assert(I != IEnd && "Iterator range cannot be empty"); @@ -151,9 +151,9 @@ MaybeConstructOverloadSet(ASTContext &Context, static Sema::LookupResult MergeLookupResults(ASTContext &Context, LookupResultsTy &Results) { typedef Sema::LookupResult LResult; - typedef llvm::SmallVector DeclsVecTy; + typedef llvm::SmallPtrSet DeclsSetTy; - DeclsVecTy FoundDecls; + DeclsSetTy FoundDecls; OverloadedFunctionDecl *FoundOverloaded = 0; LookupResultsTy::iterator I = Results.begin(), End = Results.end(); @@ -171,58 +171,27 @@ MergeLookupResults(ASTContext &Context, LookupResultsTy &Results) { break; case LResult::Found: - FoundDecls.push_back(cast(I->getAsDecl())); + FoundDecls.insert(I->getAsDecl()); break; case LResult::AmbiguousBaseSubobjectTypes: case LResult::AmbiguousBaseSubobjects: { - LResult Ambig = *I; - // Free rest of OverloadedFunctionDecl, and other BasePaths - // stored in LookupResults. -#if 0 - // FIXME: - // It should not happen, when we look start in each DeclContext only once. - // See FIXME in CppLookupName. - assert(Results.size() == 1 && "Multiple LookupResults should be not case " - "here, since using-directives can't occur at class scope."); -#else - if (FoundOverloaded) - FoundOverloaded->Destroy(Context); - - for (++I; I != End; ++I) { - if (I->getKind() == LResult::FoundOverloaded) - cast(I->getAsDecl())->Destroy(Context); - else if (BasePaths *Paths = I->getBasePaths()) - delete Paths; - assert(I->getKind() != LResult::AmbiguousReference && - "Shouldn't get ambiguous reference here."); - } -#endif - return Ambig; + assert(Results.size() == 1 && "Multiple LookupResults should be not case " + "here, since using-directives can't occur at class scope."); + return *I; } case LResult::FoundOverloaded: - if (FoundOverloaded) { + if (FoundOverloaded) // We have one spare OverloadedFunctionDecl already, so we store // its function decls. -#if 0 - FIXME: As soon as, stop call MaybeConstructOverloadSet here, - which requires iterator::reference of type NamedDecl*, FoundDecls - can be SmallVector - or when Lookup*Name() starts return NamedDecl's* instead of Decl's - - this will work: - std::copy(I->begin(), I->end(), std::back_inserter(FoundDecls)); -#else - Sema::LookupResult::iterator OI = I->begin(), OEnd = I->end(); - for (; OI != OEnd; ++OI) - FoundDecls.push_back(cast(*OI)); -#endif - } else { + for (LResult::iterator + FI = I->begin(), FEnd = I->end(); FI != FEnd; ++FI) + FoundDecls.insert(*FI); + else // First time we found OverloadedFunctionDecl, we want to conserve // it, and possibly add other found Decls later. FoundOverloaded = cast(I->getAsDecl()); - } break; } } @@ -246,35 +215,33 @@ MergeLookupResults(ASTContext &Context, LookupResultsTy &Results) { // // FIXME: At this point happens too, because we are doing redundant lookups. // - DeclsVecTy::iterator DI = FoundDecls.begin(), DEnd = FoundDecls.end(); - // FIXME: Using SmallPtrSet instead would be better, once OverloadedFunctionDecl - // dies. - std::sort(DI, DEnd); - DEnd = std::unique(DI, DEnd); + DeclsSetTy::iterator DI = FoundDecls.begin(), DEnd = FoundDecls.end(); if (FoundOverloaded) { // We found overloaded functions result. We want to add any other // found decls, that are not already in FoundOverloaded, and are functions // or methods. OverloadedFunctionDecl::function_iterator - FBegin = FoundOverloaded->function_begin(), + FI = FoundOverloaded->function_begin(), FEnd = FoundOverloaded->function_end(); - // FIXME: This is O(n^2)! - for (; DI < DEnd; ++DI) { - FunctionDecl *Fun = dyn_cast(*DI); - if (Fun && (std::find(FBegin, FEnd, Fun) != FEnd)) { /* Skip.*/ } - else DEnd = std::remove(DI, DEnd, *DI); + + for (; FI < FEnd; ++FI) { + if (FoundDecls.count(*FI)) + FoundDecls.erase(*FI); } - for (DI = FoundDecls.begin(); DI != DEnd; ++DI) - FoundOverloaded->addOverload(cast(*DI)); + DI = FoundDecls.begin(), DEnd = FoundDecls.end(); + + for (; DI != DEnd; ++DI) + if (FunctionDecl *Fun = dyn_cast(*DI)) + FoundOverloaded->addOverload(Fun); return LResult::CreateLookupResult(Context, FoundOverloaded); - } else if (std::size_t FoundLen = std::distance(FoundDecls.begin(), DEnd)) { + } else if (std::size_t FoundLen = FoundDecls.size()) { // We might found multiple TagDecls pointing at same definition. if (TagDecl *R = dyn_cast(*FoundDecls.begin())) { TagDecl *Canonical = Context.getCanonicalDecl(R); - DeclsVecTy::iterator RI = FoundDecls.begin(), REnd = DEnd; + DeclsSetTy::iterator RI = FoundDecls.begin(), REnd = DEnd; for (;;) { ++RI; if (RI == REnd) { @@ -288,12 +255,14 @@ MergeLookupResults(ASTContext &Context, LookupResultsTy &Results) { } // We might find FunctionDecls in two (or more) distinct DeclContexts. - // 3.4.1.p1 ... Name lookup may associate more than one declaration with + // + // C++ [basic.lookup].p1: + // ... Name lookup may associate more than one declaration with // a name if it finds the name to be a function name; the declarations // are said to form a set of overloaded functions (13.1). // Overload resolution (13.3) takes place after name lookup has succeeded. - - Decl *D = MaybeConstructOverloadSet(Context, DI, DEnd); + // + NamedDecl *D = MaybeConstructOverloadSet(Context, DI, DEnd); if ((FoundLen == 1) || isa(D)) return LResult::CreateLookupResult(Context, D); @@ -337,38 +306,8 @@ getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind, return IDNS; } -// Return qualified name for Decl D, like A::B::i, for i being member of -// namespace A::B. -std::string -getQualifiedName(Decl *D) { - std::vector Names; - std::string QualName; - DeclContext *Ctx = D->getDeclContext(); - - if (Ctx->isFunctionOrMethod()) - return cast(D)->getNameAsString(); - - while (Ctx) { - if (Ctx->isFunctionOrMethod()) { - // FIXME: That probably is happend, because D was member of local - // scope class/struct/union. How do we handle this case? - break; - } - if (NamedDecl *ND = dyn_cast(Ctx)) { - Names.push_back(ND->getNameAsString()); - } else { - break; - } - Ctx = Ctx->getParent(); - } - for (std::vector::reverse_iterator I= Names.rbegin(), End =Names.rend(); I!=End; ++I) - QualName += *I + "::"; - QualName += cast(D)->getNameAsString(); - return QualName; -} - Sema::LookupResult -Sema::LookupResult::CreateLookupResult(ASTContext &Context, Decl *D) { +Sema::LookupResult::CreateLookupResult(ASTContext &Context, NamedDecl *D) { LookupResult Result; Result.StoredKind = (D && isa(D))? OverloadedDeclSingleDecl : SingleDecl; @@ -462,10 +401,10 @@ Sema::LookupResult::LookupKind Sema::LookupResult::getKind() const { /// 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. -Decl *Sema::LookupResult::getAsDecl() const { +NamedDecl *Sema::LookupResult::getAsDecl() const { switch (StoredKind) { case SingleDecl: - return reinterpret_cast(First); + return reinterpret_cast(First); case OverloadedDeclFromIdResolver: return MaybeConstructOverloadSet(*Context, @@ -502,10 +441,10 @@ Sema::LookupResult::iterator::reference Sema::LookupResult::iterator::operator*() const { switch (Result->StoredKind) { case SingleDecl: - return reinterpret_cast(Current); + return reinterpret_cast(Current); case OverloadedDeclSingleDecl: - return *reinterpret_cast(Current); + return *reinterpret_cast(Current); case OverloadedDeclFromIdResolver: return *IdentifierResolver::iterator::getFromOpaqueValue(Current); @@ -525,11 +464,11 @@ Sema::LookupResult::iterator::operator*() const { Sema::LookupResult::iterator& Sema::LookupResult::iterator::operator++() { switch (Result->StoredKind) { case SingleDecl: - Current = reinterpret_cast((Decl*)0); + Current = reinterpret_cast((NamedDecl*)0); break; case OverloadedDeclSingleDecl: { - Decl ** I = reinterpret_cast(Current); + NamedDecl ** I = reinterpret_cast(Current); ++I; Current = reinterpret_cast(I); break; @@ -590,7 +529,7 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, assert(getLangOptions().CPlusPlus && "Can perform only C++ lookup"); unsigned IDNS - = getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true); + = getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true); Scope *Initial = S; IdentifierResolver::iterator I = IdResolver.begin(Name), @@ -613,7 +552,7 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, // ++i; // finds local 'i', A::i appears at global scope // } // } - // + // for (; S && isFunctionLocalScope(S); S = S->getParent()) { // Check whether the IdResolver has anything in this scope. for (; I != IEnd && S->isDeclScope(*I); ++I) { @@ -658,7 +597,8 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, // DeclContext, so we don't build it for each lookup! UsingDirectivesTy UDirs; for (Scope *SC = Initial; SC; SC = SC->getParent()) - AddScopeUsingDirectives(SC, UDirs); + if (SC->getFlags() & Scope::DeclScope) + AddScopeUsingDirectives(SC, UDirs); // Sort heapified UsingDirectiveDecls. std::sort_heap(UDirs.begin(), UDirs.end()); @@ -1131,14 +1071,13 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name, Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange; - Decl **DI = reinterpret_cast(Result.First), - **DEnd = reinterpret_cast(Result.Last); + NamedDecl **DI = reinterpret_cast(Result.First), + **DEnd = reinterpret_cast(Result.Last); for (; DI != DEnd; ++DI) - Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) - << getQualifiedName(*DI); + Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI; - delete[] reinterpret_cast(Result.First); + delete[] reinterpret_cast(Result.First); return true; } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index f1b8617dae..c46731e515 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -32,7 +32,7 @@ Sema::DeclTy *Sema::isTemplateName(IdentifierInfo &II, Scope *S, return 0; DC = static_cast(SS->getScopeRep()); } - Decl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName); + NamedDecl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName); if (IIDecl) { // FIXME: We need to represent templates via some kind of @@ -94,7 +94,7 @@ Sema::DeclTy *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Invalid = false; if (ParamName) { - Decl *PrevDecl = LookupName(S, ParamName, LookupTagName); + NamedDecl *PrevDecl = LookupName(S, ParamName, LookupTagName); if (PrevDecl && PrevDecl->isTemplateParameter()) Invalid = Invalid || DiagnoseTemplateParameterShadow(ParamNameLoc, PrevDecl); @@ -130,7 +130,7 @@ Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, IdentifierInfo *ParamName = D.getIdentifier(); if (ParamName) { - Decl *PrevDecl = LookupName(S, ParamName, LookupTagName); + NamedDecl *PrevDecl = LookupName(S, ParamName, LookupTagName); if (PrevDecl && PrevDecl->isTemplateParameter()) Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);