Index: include/clang/Sema/Lookup.h =================================================================== --- include/clang/Sema/Lookup.h +++ include/clang/Sema/Lookup.h @@ -197,6 +197,7 @@ Shadowed(std::move(Other.Shadowed)) { Other.Paths = nullptr; Other.Diagnose = false; + Other.AddUsingDirectives = false; } LookupResult &operator=(LookupResult &&Other) { @@ -219,6 +220,7 @@ Shadowed = std::move(Other.Shadowed); Other.Paths = nullptr; Other.Diagnose = false; + Other.AddUsingDirectives = false; return *this; } @@ -451,6 +453,10 @@ /// lookup. void setShadowed() { Shadowed = true; } + /// Determine wheter the lookup result should store using directives. + bool isAddUsingDirectives() const { return AddUsingDirectives; } + void setAddUsingDirectives() { AddUsingDirectives = true; } + /// Resolves the result kind of the lookup, possibly hiding /// decls. /// @@ -738,6 +744,9 @@ /// declaration that we skipped. This only happens when \c LookupKind /// is \c LookupRedeclarationWithLinkage. bool Shadowed = false; + + /// True if the using directives should be added to the results. + bool AddUsingDirectives = false; }; /// Consumes visible declarations found when searching for Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -4037,9 +4037,10 @@ // odr-use cannot be determined from the current context (for instance, // because the name denotes a virtual function and was written without an // explicit nested-name-specifier). - void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool MightBeOdrUse); + void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool MightBeOdrUse, + CXXScopeSpec *SS = nullptr, Expr *E = nullptr); void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, - bool MightBeOdrUse = true); + bool MightBeOdrUse = true, Expr *E = nullptr); void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var); void MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base = nullptr); void MarkMemberReferenced(MemberExpr *E); @@ -4047,6 +4048,10 @@ void UpdateMarkingForLValueToRValue(Expr *E); void CleanupVarDeclMarking(); + void MarkNamespaceAliasReferenced(NamedDecl *ND); + void MarkUsingReferenced(NamedDecl *ND, SourceLocation Loc, + CXXScopeSpec *SS = nullptr, Expr *E = nullptr); + enum TryCaptureKind { TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef }; Index: include/clang/Sema/SemaInternal.h =================================================================== --- include/clang/Sema/SemaInternal.h +++ include/clang/Sema/SemaInternal.h @@ -66,10 +66,10 @@ // If the variable must be captured: // - if FunctionScopeIndexToStopAt is null, capture it in the CurContext // - else capture it in the DeclContext that maps to the -// *FunctionScopeIndexToStopAt on the FunctionScopeInfo stack. -inline void MarkVarDeclODRUsed(VarDecl *Var, - SourceLocation Loc, Sema &SemaRef, - const unsigned *const FunctionScopeIndexToStopAt) { +// *FunctionScopeIndexToStopAt on the FunctionScopeInfo stack. +inline void MarkVarDeclODRUsed(VarDecl *Var, SourceLocation Loc, Sema &SemaRef, + const unsigned *const FunctionScopeIndexToStopAt, + Expr *RefExpr = nullptr) { // Keep track of used but undefined variables. // FIXME: We shouldn't suppress this warning for static data members. if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly && @@ -88,6 +88,7 @@ FunctionScopeIndexToStopAt); Var->markUsed(SemaRef.Context); + SemaRef.MarkUsingReferenced(Var, Loc, /*SS=*/nullptr, RefExpr); } /// Return a DLL attribute from the declaration. Index: lib/Sema/SemaCXXScopeSpec.cpp =================================================================== --- lib/Sema/SemaCXXScopeSpec.cpp +++ lib/Sema/SemaCXXScopeSpec.cpp @@ -694,7 +694,7 @@ } if (auto *TD = dyn_cast_or_null(SD)) - MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false); + MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false, &SS); // If we're just performing this lookup for error-recovery purposes, // don't extend the nested-name-specifier. Just return now. Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -477,7 +477,7 @@ DiagnoseUseOfDecl(IIDecl, NameLoc); T = Context.getTypeDeclType(TD); - MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false); + MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false, SS); } else if (ObjCInterfaceDecl *IDecl = dyn_cast(IIDecl)) { (void)DiagnoseUseOfDecl(IDecl, NameLoc); if (!HasTrailingDot) @@ -1091,7 +1091,7 @@ NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl(); if (TypeDecl *Type = dyn_cast(FirstDecl)) { DiagnoseUseOfDecl(Type, NameLoc); - MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false); + MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false, &SS); QualType T = Context.getTypeDeclType(Type); if (SS.isNotEmpty()) return buildNestedType(*this, SS, T, NameLoc); Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -3927,7 +3927,7 @@ if (BaseType.isNull()) { BaseType = Context.getTypeDeclType(TyD); - MarkAnyDeclReferenced(TyD->getLocation(), TyD, /*OdrUse=*/false); + MarkAnyDeclReferenced(TyD->getLocation(), TyD, /*OdrUse=*/false, &SS); if (SS.isSet()) { BaseType = Context.getElaboratedType(ETK_None, SS.getScopeRep(), BaseType); @@ -15511,3 +15511,76 @@ return NewPD; } + +/// Mark the alias declaration and any associated chain as referenced. +void Sema::MarkNamespaceAliasReferenced(NamedDecl *ND) { + if (!ND || ND->isReferenced()) + return; + NamespaceAliasDecl *NA; + while ((NA = dyn_cast(ND)) && !NA->isReferenced()) { + NA->setReferenced(); + ND = NA->getAliasedNamespace(); + if (auto *NNS = NA->getQualifier()) + MarkNamespaceAliasReferenced(NNS->getAsNamespaceAlias()); + } +} + +/// Mark as referenced any 'using' statement (using-declaration, +/// using directive or namespace alias), that have introduced the +/// given declaration into the current context. +void Sema::MarkUsingReferenced(NamedDecl *ND, SourceLocation Loc, + CXXScopeSpec *SS, Expr *E) { + // The declaration was not defined in a namespace. + auto *DC = ND->getDeclContext(); + if (!DC->isNamespace()) + return; + + // If the declaration was accessed explicitly using a namespace context, + // follow any associated namespace chain, as those declarations must be + // marked as referenced as well. + // Example: + // + // namespace N { + // int var; + // } + // + // void Fd() { + // namespace NA = N; // Referenced + // namespace NB = NA; // Referenced + // NB::var = 4; + // } + + if (auto *NNS = SS ? SS->getScopeRep() + : E ? cast(E)->getQualifier() : nullptr) { + MarkNamespaceAliasReferenced(NNS->getAsNamespaceAlias()); + return; + } + + // Lookup the named declaration. + LookupResult R(*this, ND->getDeclName(), Loc, LookupAnyName); + R.suppressDiagnostics(); + R.setAddUsingDirectives(); + LookupName(R, getCurScope()); + + // Any using-directive namespace target. + auto *Target = dyn_cast(DC); + + for (auto *I : R) { + NamedDecl *D = I->getUnderlyingDecl(); + if (auto *UD = dyn_cast(D)) { + // The declaration was introduced by a 'using-declaration'. + UD->setReferenced(); + for (auto *UsingShadow : UD->shadows()) + UsingShadow->setReferenced(); + if (auto *NNS = UD->getQualifier()) + MarkNamespaceAliasReferenced(NNS->getAsNamespaceAlias()); + return; + } else if (auto *UDir = dyn_cast(D)) + // The declaration was introduced by a 'using-directive'. + if (UDir->getNominatedNamespace() == Target) { + UDir->setReferenced(); + MarkNamespaceAliasReferenced(UDir->getNominatedNamespaceAsWritten()); + return; + } + } +} Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -14290,7 +14290,7 @@ /// Mark a function referenced, and check whether it is odr-used /// (C++ [basic.def.odr]p2, C99 6.9p3) void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, - bool MightBeOdrUse) { + bool MightBeOdrUse, Expr *E) { assert(Func && "No function?"); Func->setReferenced(); @@ -14457,6 +14457,7 @@ } Func->markUsed(Context); + MarkUsingReferenced(Func, Loc, /*SS=*/nullptr, E); } static void @@ -15321,7 +15322,7 @@ SemaRef.MaybeODRUseExprs.insert(E); } else if (OdrUseContext) { MarkVarDeclODRUsed(Var, Loc, SemaRef, - /*MaxFunctionScopeIndex ptr*/ nullptr); + /*MaxFunctionScopeIndex ptr*/ nullptr, E); } else if (isOdrUseContext(SemaRef, /*SkipDependentUses*/false)) { // If this is a dependent context, we don't need to mark variables as // odr-used, but we may still need to track them for lambda capture. @@ -15369,7 +15370,7 @@ return; } - SemaRef.MarkAnyDeclReferenced(Loc, D, MightBeOdrUse); + SemaRef.MarkAnyDeclReferenced(Loc, D, MightBeOdrUse, /*SS=*/nullptr, E); // If this is a call to a method via a cast, also mark the method in the // derived class used in case codegen can devirtualize the call. @@ -15390,7 +15391,7 @@ CXXMethodDecl *DM = MD->getDevirtualizedMethod( ME->getBase(), SemaRef.getLangOpts().AppleKext); if (DM) - SemaRef.MarkAnyDeclReferenced(Loc, DM, MightBeOdrUse); + SemaRef.MarkAnyDeclReferenced(Loc, DM, MightBeOdrUse, /*SS=*/nullptr, E); } /// Perform reference-marking and odr-use handling for a DeclRefExpr. @@ -15430,7 +15431,8 @@ /// functions and variables. This method should not be used when building a /// normal expression which refers to a variable. void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, - bool MightBeOdrUse) { + bool MightBeOdrUse, CXXScopeSpec *SS, + Expr *E) { if (MightBeOdrUse) { if (auto *VD = dyn_cast(D)) { MarkVariableReferenced(Loc, VD); @@ -15438,10 +15440,11 @@ } } if (auto *FD = dyn_cast(D)) { - MarkFunctionReferenced(Loc, FD, MightBeOdrUse); + MarkFunctionReferenced(Loc, FD, MightBeOdrUse, E); return; } D->setReferenced(); + MarkUsingReferenced(dyn_cast(D), Loc, SS, E); } namespace { Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -250,7 +250,7 @@ if (TypeDecl *Type = Found.getAsSingle()) { QualType T = Context.getTypeDeclType(Type); - MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false); + MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false, &SS); if (SearchType.isNull() || SearchType->isDependentType() || Context.hasSameUnqualifiedType(T, SearchType)) { Index: lib/Sema/SemaLookup.cpp =================================================================== --- lib/Sema/SemaLookup.cpp +++ lib/Sema/SemaLookup.cpp @@ -95,6 +95,9 @@ ListTy list; llvm::SmallPtrSet visited; + using UsingDirs = llvm::SmallPtrSet; + UsingDirs usings; + public: UnqualUsingDirectiveSet(Sema &SemaRef) : SemaRef(SemaRef) {} @@ -184,6 +187,14 @@ Common = Common->getPrimaryContext(); list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common)); + // Insert the using directive. + usings.insert(UD); + } + + // Add the collected using directives to the given lookup results. + void addUsingDirective(LookupResult &R) { + for (auto *I : usings) + R.addDecl(I); } void done() { @@ -1048,6 +1059,13 @@ }; } // end anonymous namespace +// Add any using directives to the lookup results. +static void AddUsingDirectives(LookupResult &R, + UnqualUsingDirectiveSet &UDirs) { + if (R.isAddUsingDirectives()) + UDirs.addUsingDirective(R); +} + bool Sema::CppLookupName(LookupResult &R, Scope *S) { assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup"); @@ -1215,6 +1233,7 @@ UDirs.visitScopeChain(Initial, InnermostFileScope); UDirs.done(); + AddUsingDirectives(R, UDirs); VisitedUsingDirectives = true; } @@ -1255,6 +1274,7 @@ if (!VisitedUsingDirectives) { UDirs.visitScopeChain(Initial, S); UDirs.done(); + AddUsingDirectives(R, UDirs); } // If we're not performing redeclaration lookup, do not look for local Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -9679,7 +9679,7 @@ // We found a type. Build an ElaboratedType, since the // typename-specifier was just sugar. - MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false); + MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false, &SS); return Context.getElaboratedType(Keyword, QualifierLoc.getNestedNameSpecifier(), Context.getTypeDeclType(Type)); Index: test/PCH/cxx-templates.cpp =================================================================== --- test/PCH/cxx-templates.cpp +++ test/PCH/cxx-templates.cpp @@ -5,12 +5,12 @@ // Test with pch. // RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -x c++-header -emit-pch -o %t %S/cxx-templates.h // RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -include-pch %t -verify %s -ast-dump -o - -// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - -error-on-deserialized-decl doNotDeserialize -DNO_ERRORS | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - -DNO_ERRORS | FileCheck %s // Test with modules. // RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -x c++-header -emit-pch -o %t %S/cxx-templates.h // RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -include-pch %t -verify %s -ast-dump -o - -// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -include-pch %t %s -emit-llvm -o - -error-on-deserialized-decl doNotDeserialize -DNO_ERRORS -fmodules-ignore-macro=NO_ERRORS | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -include-pch %t %s -emit-llvm -o - -DNO_ERRORS -fmodules-ignore-macro=NO_ERRORS | FileCheck %s // Test with pch and delayed template parsing. // RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fdelayed-template-parsing -fexceptions -x c++-header -emit-pch -o %t %S/cxx-templates.h Index: test/SemaCXX/referenced_alias_declaration_1.cpp =================================================================== --- test/SemaCXX/referenced_alias_declaration_1.cpp +++ test/SemaCXX/referenced_alias_declaration_1.cpp @@ -0,0 +1,83 @@ +// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace + +namespace N { +int var; +} // namespace N + +void Fa() { + namespace NN = N; // Referenced + using namespace NN; // Referenced + var = 1; +} + +void Fb() { + namespace NA = N; // Referenced + namespace NB = NA; // Referenced + namespace NC = NB; // Referenced + using namespace NC; // Referenced + var = 2; + namespace ND = NC; +} + +void Fc() { + namespace NA = N; + using namespace NA; + N::var = 3; +} + +void Fd() { + namespace NA = N; // Referenced + namespace NB = NA; // Referenced + NB::var = 4; +} + +//CHECK: |-FunctionDecl {{.*}} Fa 'void ()' +//CHECK-NEXT: | `-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-NamespaceAliasDecl {{.*}} referenced NN +//CHECK-NEXT: | | `-Namespace {{.*}} 'N' +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-UsingDirectiveDecl {{.*}} referenced Namespace {{.*}} 'N' +//CHECK-NEXT: | `-BinaryOperator {{.*}} 'int' lvalue '=' +//CHECK-NEXT: | |-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'var' 'int' +//CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1 +//CHECK-NEXT: |-FunctionDecl {{.*}} Fb 'void ()' +//CHECK-NEXT: | `-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-NamespaceAliasDecl {{.*}} referenced NA +//CHECK-NEXT: | | `-Namespace {{.*}} 'N' +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-NamespaceAliasDecl {{.*}} referenced NB +//CHECK-NEXT: | | `-NamespaceAlias {{.*}} 'NA' +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-NamespaceAliasDecl {{.*}} referenced NC +//CHECK-NEXT: | | `-NamespaceAlias {{.*}} 'NB' +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-UsingDirectiveDecl {{.*}} referenced Namespace {{.*}} 'N' +//CHECK-NEXT: | |-BinaryOperator {{.*}} 'int' lvalue '=' +//CHECK-NEXT: | | |-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'var' 'int' +//CHECK-NEXT: | | `-IntegerLiteral {{.*}} 'int' 2 +//CHECK-NEXT: | `-DeclStmt {{.*}} +//CHECK-NEXT: | `-NamespaceAliasDecl {{.*}} ND +//CHECK-NEXT: | `-NamespaceAlias {{.*}} 'NC' +//CHECK-NEXT: |-FunctionDecl {{.*}} Fc 'void ()' +//CHECK-NEXT: | `-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-NamespaceAliasDecl {{.*}} NA +//CHECK-NEXT: | | `-Namespace {{.*}} 'N' +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-UsingDirectiveDecl {{.*}} Namespace {{.*}} 'N' +//CHECK-NEXT: | `-BinaryOperator {{.*}} 'int' lvalue '=' +//CHECK-NEXT: | |-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'var' 'int' +//CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 3 +//CHECK-NEXT: `-FunctionDecl {{.*}} Fd 'void ()' +//CHECK-NEXT: `-CompoundStmt {{.*}} +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-NamespaceAliasDecl {{.*}} referenced NA +//CHECK-NEXT: | `-Namespace {{.*}} 'N' +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-NamespaceAliasDecl {{.*}} referenced NB +//CHECK-NEXT: | `-NamespaceAlias {{.*}} 'NA' +//CHECK-NEXT: `-BinaryOperator {{.*}} 'int' lvalue '=' +//CHECK-NEXT: |-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'var' 'int' +//CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 4 Index: test/SemaCXX/referenced_alias_declaration_2.cpp =================================================================== --- test/SemaCXX/referenced_alias_declaration_2.cpp +++ test/SemaCXX/referenced_alias_declaration_2.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace + +namespace A { +namespace B { +namespace C { +typedef int Integer; +} // namespace C +} // namespace B +} // namespace A + +void foo() { + { + namespace N_A = A; // Referenced + { + namespace N_AB = N_A::B; // Referenced + { + namespace N_ABC = N_AB::C; // Referenced + { + using N_ABC::Integer; // Referenced + Integer var; + } + } + } + } + { + namespace N_A = A; + { + namespace N_AB = N_A::B; + { + namespace N_ABC = N_AB::C; + { + A::B::C::Integer var; + } + } + } + } +} + +//CHECK: `-FunctionDecl {{.*}} foo 'void ()' +//CHECK-NEXT: `-CompoundStmt {{.*}} +//CHECK-NEXT: |-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-NamespaceAliasDecl {{.*}} referenced N_A +//CHECK-NEXT: | | `-Namespace {{.*}} 'A' +//CHECK-NEXT: | `-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-NamespaceAliasDecl {{.*}} referenced N_AB +//CHECK-NEXT: | | `-Namespace {{.*}} 'B' +//CHECK-NEXT: | `-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-NamespaceAliasDecl {{.*}} referenced N_ABC +//CHECK-NEXT: | | `-Namespace {{.*}} 'C' +//CHECK-NEXT: | `-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-UsingDecl {{.*}} referenced N_ABC::Integer +//CHECK-NEXT: | `-DeclStmt {{.*}} +//CHECK-NEXT: | `-VarDecl {{.*}} var 'A::B::C::Integer':'int' +//CHECK-NEXT: `-CompoundStmt {{.*}} +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-NamespaceAliasDecl {{.*}} N_A +//CHECK-NEXT: | `-Namespace {{.*}} 'A' +//CHECK-NEXT: `-CompoundStmt {{.*}} +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-NamespaceAliasDecl {{.*}} N_AB +//CHECK-NEXT: | `-Namespace {{.*}} 'B' +//CHECK-NEXT: `-CompoundStmt {{.*}} +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-NamespaceAliasDecl {{.*}} N_ABC +//CHECK-NEXT: | `-Namespace {{.*}} 'C' +//CHECK-NEXT: `-CompoundStmt {{.*}} +//CHECK-NEXT: `-DeclStmt {{.*}} +//CHECK-NEXT: `-VarDecl {{.*}} var 'A::B::C::Integer':'int' Index: test/SemaCXX/referenced_using_all.cpp =================================================================== --- test/SemaCXX/referenced_using_all.cpp +++ test/SemaCXX/referenced_using_all.cpp @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace + +namespace A { +typedef char Char; +typedef int Integer; +typedef float Float; +int var; +} // namespace A + +using A::Char; +using A::Float; +using A::Integer; // Referenced + +namespace B { +using A::Char; // Referenced +template +T FuncTempl(T p1, Char p2) { + using A::Float; // Referenced + typedef Float Type; + Integer I; + return p1; +} +} // namespace B + +using A::Char; // Referenced +using A::Integer; +namespace ND1 = A; +void foo() { + using A::Integer; // Referenced + namespace ND2 = ND1; // Referenced + { + Integer Ivar; + namespace ND3 = ND2; // Referenced + { + namespace ND4 = ND3; // Referenced + Char Cvar; + { + using ND4::var; // Referenced + var = 1; + } + } + } + using A::Char; // Referenced + using namespace ::B; // Referenced + FuncTempl(1, 'a'); +} + +//CHECK: |-UsingDecl {{.*}} A::Char +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit Typedef {{.*}} 'Char' +//CHECK-NEXT: | `-TypedefType {{.*}} 'A::Char' sugar +//CHECK-NEXT: | |-Typedef {{.*}} 'Char' +//CHECK-NEXT: | `-BuiltinType {{.*}} 'char' +//CHECK-NEXT: |-UsingDecl {{.*}} A::Float +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit Typedef {{.*}} 'Float' +//CHECK-NEXT: | `-TypedefType {{.*}} 'A::Float' sugar +//CHECK-NEXT: | |-Typedef {{.*}} 'Float' +//CHECK-NEXT: | `-BuiltinType {{.*}} 'float' +//CHECK-NEXT: |-UsingDecl {{.*}} referenced A::Integer +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit referenced Typedef {{.*}} 'Integer' +//CHECK-NEXT: | `-TypedefType {{.*}} 'A::Integer' sugar +//CHECK-NEXT: | |-Typedef {{.*}} 'Integer' +//CHECK-NEXT: | `-BuiltinType {{.*}} 'int' +//CHECK-NEXT: |-NamespaceDecl {{.*}} B +//CHECK-NEXT: | |-UsingDecl {{.*}} referenced A::Char +//CHECK-NEXT: | |-UsingShadowDecl {{.*}} implicit referenced Typedef {{.*}} 'Char' +//CHECK-NEXT: | | `-TypedefType {{.*}} 'A::Char' sugar +//CHECK-NEXT: | | |-Typedef {{.*}} 'Char' +//CHECK-NEXT: | | `-BuiltinType {{.*}} 'char' +//CHECK-NEXT: | `-FunctionTemplateDecl {{.*}} FuncTempl +//CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} referenced class depth 0 index 0 T +//CHECK-NEXT: | |-FunctionDecl {{.*}} FuncTempl 'T (T, A::Char)' +//CHECK-NEXT: | | |-ParmVarDecl {{.*}} referenced p1 'T' +//CHECK-NEXT: | | |-ParmVarDecl {{.*}} 'A::Char':'char' +//CHECK-NEXT: | | `-CompoundStmt {{.*}} +//CHECK-NEXT: | | |-DeclStmt {{.*}} +//CHECK-NEXT: | | | `-UsingDecl {{.*}} referenced A::Float +//CHECK-NEXT: | | |-DeclStmt {{.*}} +//CHECK-NEXT: | | | `-TypedefDecl {{.*}} Type 'A::Float':'float' +//CHECK-NEXT: | | | `-TypedefType {{.*}} 'A::Float' sugar +//CHECK-NEXT: | | | |-Typedef {{.*}} 'Float' +//CHECK-NEXT: | | | `-BuiltinType {{.*}} 'float' +//CHECK-NEXT: | | |-DeclStmt {{.*}} +//CHECK-NEXT: | | | `-VarDecl {{.*}} I 'A::Integer':'int' +//CHECK-NEXT: | | `-ReturnStmt {{.*}} +//CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'p1' 'T' +//CHECK-NEXT: | `-FunctionDecl {{.*}} used FuncTempl 'char (char, A::Char)' +//CHECK-NEXT: | |-TemplateArgument type 'char' +//CHECK-NEXT: | |-ParmVarDecl {{.*}} used p1 'char':'char' +//CHECK-NEXT: | |-ParmVarDecl {{.*}} p2 'A::Char':'char' +//CHECK-NEXT: | `-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-UsingDecl {{.*}} A::Float +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-TypedefDecl {{.*}} Type 'A::Float':'float' +//CHECK-NEXT: | | `-TypedefType {{.*}} 'A::Float' sugar +//CHECK-NEXT: | | |-Typedef {{.*}} 'Float' +//CHECK-NEXT: | | `-BuiltinType {{.*}} 'float' +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-VarDecl {{.*}} I 'A::Integer':'int' +//CHECK-NEXT: | `-ReturnStmt {{.*}} +//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'char':'char' +//CHECK-NEXT: | `-DeclRefExpr {{.*}} 'char':'char' lvalue ParmVar {{.*}} 'p1' 'char':'char' +//CHECK-NEXT: |-UsingDecl {{.*}} referenced A::Char +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit referenced Typedef {{.*}} 'Char' +//CHECK-NEXT: | `-TypedefType {{.*}} 'A::Char' sugar +//CHECK-NEXT: | |-Typedef {{.*}} 'Char' +//CHECK-NEXT: | `-BuiltinType {{.*}} 'char' +//CHECK-NEXT: |-UsingDecl {{.*}} A::Integer +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit Typedef {{.*}} 'Integer' +//CHECK-NEXT: | `-TypedefType {{.*}} 'A::Integer' sugar +//CHECK-NEXT: | |-Typedef {{.*}} 'Integer' +//CHECK-NEXT: | `-BuiltinType {{.*}} 'int' +//CHECK-NEXT: |-NamespaceAliasDecl {{.*}} referenced ND1 +//CHECK-NEXT: | `-Namespace {{.*}} 'A' +//CHECK-NEXT: `-FunctionDecl {{.*}} foo 'void ()' +//CHECK-NEXT: `-CompoundStmt {{.*}} +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-UsingDecl {{.*}} referenced A::Integer +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-NamespaceAliasDecl {{.*}} referenced ND2 +//CHECK-NEXT: | `-NamespaceAlias {{.*}} 'ND1' +//CHECK-NEXT: |-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-VarDecl {{.*}} Ivar 'A::Integer':'int' +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-NamespaceAliasDecl {{.*}} referenced ND3 +//CHECK-NEXT: | | `-NamespaceAlias {{.*}} 'ND2' +//CHECK-NEXT: | `-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-NamespaceAliasDecl {{.*}} referenced ND4 +//CHECK-NEXT: | | `-NamespaceAlias {{.*}} 'ND3' +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-VarDecl {{.*}} Cvar 'A::Char':'char' +//CHECK-NEXT: | `-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-UsingDecl {{.*}} referenced ND4::var +//CHECK-NEXT: | `-BinaryOperator {{.*}} 'int' lvalue '=' +//CHECK-NEXT: | |-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'var' 'int' (UsingShadow {{.*}} 'var') +//CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1 +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-UsingDecl {{.*}} referenced A::Char +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-UsingDirectiveDecl {{.*}} referenced Namespace {{.*}} 'B' +//CHECK-NEXT: `-CallExpr {{.*}} 'char':'char' +//CHECK-NEXT: |-ImplicitCastExpr {{.*}} 'char (*)(char, A::Char)' +//CHECK-NEXT: | `-DeclRefExpr {{.*}} 'char (char, A::Char)' lvalue Function {{.*}} 'FuncTempl' 'char (char, A::Char)' (FunctionTemplate {{.*}} 'FuncTempl') +//CHECK-NEXT: |-ImplicitCastExpr {{.*}} 'char':'char' +//CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1 +//CHECK-NEXT: `-CharacterLiteral {{.*}} 'char' 97 Index: test/SemaCXX/referenced_using_declaration_1.cpp =================================================================== --- test/SemaCXX/referenced_using_declaration_1.cpp +++ test/SemaCXX/referenced_using_declaration_1.cpp @@ -0,0 +1,102 @@ +// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace + +namespace N { +// Types. +typedef int Integer; +struct Record { + int a; +}; + +// Variables. +int var1; +int var2; + +// Functions. +void func1(); +void func2(); +} // namespace N + +using N::func1; +using N::func2; +using N::Integer; +using N::Record; +using N::var1; +using N::var2; + +void Foo() { + using N::Integer; + N::Integer int_var; + int_var = 1; + + using N::Record; // Referenced + Record rec_var; + rec_var.a = 2; + + using N::var1; + N::var1 = 3; + + using N::var2; // Referenced + var2 = 4; + + using N::func1; + N::func1(); + + using N::func2; // Referenced + func2(); +} + +//CHECK: |-UsingDecl {{.*}} N::func1 +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit Function {{.*}} 'func1' 'void ()' +//CHECK-NEXT: |-UsingDecl {{.*}} N::func2 +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit Function {{.*}} 'func2' 'void ()' +//CHECK-NEXT: |-UsingDecl {{.*}} N::Integer +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit Typedef {{.*}} 'Integer' +//CHECK-NEXT: | `-TypedefType {{.*}} 'N::Integer' sugar +//CHECK-NEXT: | |-Typedef {{.*}} 'Integer' +//CHECK-NEXT: | `-BuiltinType {{.*}} 'int' +//CHECK-NEXT: |-UsingDecl {{.*}} N::Record +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit CXXRecord {{.*}} 'Record' +//CHECK-NEXT: | `-RecordType {{.*}} 'N::Record' +//CHECK-NEXT: | `-CXXRecord {{.*}} 'Record' +//CHECK-NEXT: |-UsingDecl {{.*}} N::var1 +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit Var {{.*}} 'var1' 'int' +//CHECK-NEXT: |-UsingDecl {{.*}} N::var2 +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit Var {{.*}} 'var2' 'int' +//CHECK-NEXT: `-FunctionDecl {{.*}} Foo 'void ()' +//CHECK-NEXT: `-CompoundStmt {{.*}} +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-UsingDecl {{.*}} N::Integer +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-VarDecl {{.*}} used int_var 'N::Integer':'int' +//CHECK-NEXT: |-BinaryOperator {{.*}} 'N::Integer':'int' lvalue '=' +//CHECK-NEXT: | |-DeclRefExpr {{.*}} 'N::Integer':'int' lvalue Var {{.*}} 'int_var' 'N::Integer':'int' +//CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1 +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-UsingDecl {{.*}} referenced N::Record +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-VarDecl {{.*}} used rec_var 'N::Record' callinit +//CHECK-NEXT: | `-CXXConstructExpr {{.*}} 'N::Record' 'void () noexcept' +//CHECK-NEXT: |-BinaryOperator {{.*}} 'int' lvalue '=' +//CHECK-NEXT: | |-MemberExpr {{.*}} 'int' lvalue .a {{.*}} +//CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'N::Record' lvalue Var {{.*}} 'rec_var' 'N::Record' +//CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 2 +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-UsingDecl {{.*}} N::var1 +//CHECK-NEXT: |-BinaryOperator {{.*}} 'int' lvalue '=' +//CHECK-NEXT: | |-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'var1' 'int' +//CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 3 +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-UsingDecl {{.*}} referenced N::var2 +//CHECK-NEXT: |-BinaryOperator {{.*}} 'int' lvalue '=' +//CHECK-NEXT: | |-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'var2' 'int' (UsingShadow {{.*}} 'var2') +//CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 4 +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-UsingDecl {{.*}} N::func1 +//CHECK-NEXT: |-CallExpr {{.*}} 'void' +//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'void (*)()' +//CHECK-NEXT: | `-DeclRefExpr {{.*}} 'void ()' lvalue Function {{.*}} 'func1' 'void ()' +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-UsingDecl {{.*}} referenced N::func2 +//CHECK-NEXT: `-CallExpr {{.*}} 'void' +//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'void (*)()' +//CHECK-NEXT: `-DeclRefExpr {{.*}} 'void ()' lvalue Function {{.*}} 'func2' 'void ()' (UsingShadow {{.*}} 'func2') Index: test/SemaCXX/referenced_using_declaration_2.cpp =================================================================== --- test/SemaCXX/referenced_using_declaration_2.cpp +++ test/SemaCXX/referenced_using_declaration_2.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace + +namespace N { +typedef int Integer; +typedef char Char; +} // namespace N + +using N::Char; // Referenced +using N::Integer; + +void Foo(int p1, N::Integer p2, Char p3) { + N::Integer var; + var = 0; +} + +using N::Integer; // Referenced +Integer Bar() { + using N::Char; + return 0; +} + +//CHECK: |-UsingDecl {{.*}} referenced N::Char +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit referenced Typedef {{.*}} 'Char' +//CHECK-NEXT: | `-TypedefType {{.*}} 'N::Char' sugar +//CHECK-NEXT: | |-Typedef {{.*}} 'Char' +//CHECK-NEXT: | `-BuiltinType {{.*}} 'char' +//CHECK-NEXT: |-UsingDecl {{.*}} N::Integer +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit Typedef {{.*}} 'Integer' +//CHECK-NEXT: | `-TypedefType {{.*}} 'N::Integer' sugar +//CHECK-NEXT: | |-Typedef {{.*}} 'Integer' +//CHECK-NEXT: | `-BuiltinType {{.*}} 'int' +//CHECK-NEXT: |-FunctionDecl {{.*}} Foo 'void (int, N::Integer, N::Char)' +//CHECK-NEXT: | |-ParmVarDecl {{.*}} p1 'int' +//CHECK-NEXT: | |-ParmVarDecl {{.*}} p2 'N::Integer':'int' +//CHECK-NEXT: | |-ParmVarDecl {{.*}} p3 'N::Char':'char' +//CHECK-NEXT: | `-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-VarDecl {{.*}} used var 'N::Integer':'int' +//CHECK-NEXT: | `-BinaryOperator {{.*}} 'N::Integer':'int' lvalue '=' +//CHECK-NEXT: | |-DeclRefExpr {{.*}} 'N::Integer':'int' lvalue Var {{.*}} 'var' 'N::Integer':'int' +//CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 0 +//CHECK-NEXT: |-UsingDecl {{.*}} referenced N::Integer +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit referenced Typedef {{.*}} 'Integer' +//CHECK-NEXT: | `-TypedefType {{.*}} 'N::Integer' sugar +//CHECK-NEXT: | |-Typedef {{.*}} 'Integer' +//CHECK-NEXT: | `-BuiltinType {{.*}} 'int' +//CHECK-NEXT: `-FunctionDecl {{.*}} Bar 'N::Integer ()' +//CHECK-NEXT: `-CompoundStmt {{.*}} +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-UsingDecl {{.*}} N::Char +//CHECK-NEXT: `-ReturnStmt {{.*}} +//CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 0 Index: test/SemaCXX/referenced_using_directive.cpp =================================================================== --- test/SemaCXX/referenced_using_directive.cpp +++ test/SemaCXX/referenced_using_directive.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace + +namespace N { +typedef int Integer; +int var; +} // namespace N + +void Fa() { + using namespace N; // Referenced + var = 1; +} + +void Fb() { + using namespace N; + N::var = 1; +} + +void Fc() { + using namespace N; // Referenced + Integer var = 1; +} + +void Fd() { + using namespace N; + N::Integer var = 1; +} + +//CHECK: |-FunctionDecl {{.*}} Fa 'void ()' +//CHECK-NEXT: | `-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-UsingDirectiveDecl {{.*}} referenced Namespace {{.*}} 'N' +//CHECK-NEXT: | `-BinaryOperator {{.*}} 'int' lvalue '=' +//CHECK-NEXT: | |-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'var' 'int' +//CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1 +//CHECK-NEXT: |-FunctionDecl {{.*}} Fb 'void ()' +//CHECK-NEXT: | `-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-UsingDirectiveDecl {{.*}} Namespace {{.*}} 'N' +//CHECK-NEXT: | `-BinaryOperator {{.*}} 'int' lvalue '=' +//CHECK-NEXT: | |-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'var' 'int' +//CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1 +//CHECK-NEXT: |-FunctionDecl {{.*}} Fc 'void ()' +//CHECK-NEXT: | `-CompoundStmt {{.*}} +//CHECK-NEXT: | |-DeclStmt {{.*}} +//CHECK-NEXT: | | `-UsingDirectiveDecl {{.*}} referenced Namespace {{.*}} 'N' +//CHECK-NEXT: | `-DeclStmt {{.*}} +//CHECK-NEXT: | `-VarDecl {{.*}} var 'N::Integer':'int' cinit +//CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1 +//CHECK-NEXT: `-FunctionDecl {{.*}} Fd 'void ()' +//CHECK-NEXT: `-CompoundStmt {{.*}} +//CHECK-NEXT: |-DeclStmt {{.*}} +//CHECK-NEXT: | `-UsingDirectiveDecl {{.*}} Namespace {{.*}} 'N' +//CHECK-NEXT: `-DeclStmt {{.*}} +//CHECK-NEXT: `-VarDecl {{.*}} var 'N::Integer':'int' cinit +//CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1