diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-01-16 22:01:39 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-01-16 22:01:39 +0000 |
| commit | 58bd01fcb63b9e2fc1117dce15b9d924cc60e171 (patch) | |
| tree | 67b48f2f51ac1ec07f951611fe542f4c97733408 /clang/lib | |
| parent | 59abdf5f3fea8becf17618ba54e25948b715f84c (diff) | |
| download | bcm5719-llvm-58bd01fcb63b9e2fc1117dce15b9d924cc60e171.tar.gz bcm5719-llvm-58bd01fcb63b9e2fc1117dce15b9d924cc60e171.zip | |
PR40329: [adl] Fix determination of associated classes when searching a
member enum and then its enclosing class.
There are situations where ADL will collect a class but not the complete
set of associated classes / namespaces of that class. When that
happened, and we later tried to collect those associated classes /
namespaces, we would previously short-circuit the lookup and not find
them. Eg, for:
struct A : B { enum E; };
if we first looked for associated classes/namespaces of A::E, we'd find
only A. But if we then tried to also collect associated
classes/namespaces of A (which should include the base class B), we
would not add B because we had already visited A.
This also fixes a minor issue where we would fail to collect associated
classes from an overloaded class member access expression naming a
static member function.
llvm-svn: 351382
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 34 |
1 files changed, 16 insertions, 18 deletions
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index effccc2f3d3..506e07670a8 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -2417,10 +2417,18 @@ namespace { InstantiationLoc(InstantiationLoc) { } + bool addClassTransitive(CXXRecordDecl *RD) { + Classes.insert(RD); + return ClassesTransitive.insert(RD); + } + Sema &S; Sema::AssociatedNamespaceSet &Namespaces; Sema::AssociatedClassSet &Classes; SourceLocation InstantiationLoc; + + private: + Sema::AssociatedClassSet ClassesTransitive; }; } // end anonymous namespace @@ -2521,15 +2529,6 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, // Add the associated namespace for this class. CollectEnclosingNamespace(Result.Namespaces, Ctx); - // Add the class itself. If we've already seen this class, we don't - // need to visit base classes. - // - // FIXME: That's not correct, we may have added this class only because it - // was the enclosing class of another class, and in that case we won't have - // added its base classes yet. - if (!Result.Classes.insert(Class)) - return; - // -- If T is a template-id, its associated namespaces and classes are // the namespace in which the template is defined; for member // templates, the member template's class; the namespaces and classes @@ -2552,6 +2551,11 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, addAssociatedClassesAndNamespaces(Result, TemplateArgs[I]); } + // Add the class itself. If we've already transitively visited this class, + // we don't need to visit base classes. + if (!Result.addClassTransitive(Class)) + return; + // Only recurse into base classes for complete types. if (!Result.S.isCompleteType(Result.InstantiationLoc, Result.S.Context.getRecordType(Class))) @@ -2577,7 +2581,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, if (!BaseType) continue; CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl()); - if (Result.Classes.insert(BaseDecl)) { + if (Result.addClassTransitive(BaseDecl)) { // Find the associated namespace for this base class. DeclContext *BaseCtx = BaseDecl->getDeclContext(); CollectEnclosingNamespace(Result.Namespaces, BaseCtx); @@ -2793,15 +2797,9 @@ void Sema::FindAssociatedClassesAndNamespaces( // in which the function or function template is defined and the // classes and namespaces associated with its (non-dependent) // parameter types and return type. - Arg = Arg->IgnoreParens(); - if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg)) - if (unaryOp->getOpcode() == UO_AddrOf) - Arg = unaryOp->getSubExpr(); - - UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg); - if (!ULE) continue; + OverloadExpr *OE = OverloadExpr::find(Arg).Expression; - for (const auto *D : ULE->decls()) { + for (const NamedDecl *D : OE->decls()) { // Look through any using declarations to find the underlying function. const FunctionDecl *FDecl = D->getUnderlyingDecl()->getAsFunction(); |

