CarlosAlbertoEnciso updated this revision to Diff 147050. CarlosAlbertoEnciso edited the summary of this revision. CarlosAlbertoEnciso added a comment.
Address the issues raised by the reviewer (rsmith). https://reviews.llvm.org/D46190 Files: include/clang/Sema/Sema.h lib/Sema/Sema.cpp lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaTemplate.cpp test/PCH/cxx-templates.cpp test/SemaCXX/referenced_alias_declaration_1.cpp test/SemaCXX/referenced_alias_declaration_2.cpp test/SemaCXX/referenced_using_all.cpp test/SemaCXX/referenced_using_declaration_1.cpp test/SemaCXX/referenced_using_declaration_2.cpp test/SemaCXX/referenced_using_directive.cpp
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; +} + +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 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; +} + +using N::Integer; +using N::Char; // Referenced + +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 {{.*}} 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 {{.*}} 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: |-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_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(); +} + +using N::Integer; +using N::Record; +using N::var1; +using N::var2; +using N::func1; +using N::func2; + +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::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: |-UsingDecl {{.*}} N::func1 +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit Function {{.*}} 'func1' 'void ()' +//CHECK-NEXT: |-UsingDecl {{.*}} N::func2 +//CHECK-NEXT: |-UsingShadowDecl {{.*}} implicit Function {{.*}} 'func2' 'void ()' +//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 (*)()' <FunctionToPointerDecay> +//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 (*)()' <FunctionToPointerDecay> +//CHECK-NEXT: `-DeclRefExpr {{.*}} 'void ()' lvalue Function {{.*}} 'func2' 'void ()' (UsingShadow {{.*}} 'func2') 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; +} + +using A::Char; +using A::Integer; // Referenced +using A::Float; + +namespace B { + using A::Char; // Referenced + template <class T> + T FuncTempl(T p1,Char p2) { + using A::Float; // Referenced + typedef Float Type; + Integer I; + return p1; + } +} + +using A::Char; // Referenced +using A::Integer; +namespace ND1 = A; +void foo() { + using A::Integer; + 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<Char>(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 {{.*}} 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: |-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: |-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' <LValueToRValue> +//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 {{.*}} <col:15> '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)' <FunctionToPointerDecay> +//CHECK-NEXT: | `-DeclRefExpr {{.*}} 'char (char, A::Char)' lvalue Function {{.*}} 'FuncTempl' 'char (char, A::Char)' (FunctionTemplate {{.*}} 'FuncTempl') +//CHECK-NEXT: |-ImplicitCastExpr {{.*}} 'char':'char' <IntegralCast> +//CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1 +//CHECK-NEXT: `-CharacterLiteral {{.*}} 'char' 97 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; + } + } +} + +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_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; +} + +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/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: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -9667,7 +9667,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: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -206,7 +206,7 @@ if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) { 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/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -14196,10 +14196,11 @@ /// 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(); + MarkUsingReferenced(Func, /*CXXScopeSpec*=*/nullptr, E); // C++11 [basic.def.odr]p3: // A function whose name appears as a potentially-evaluated expression is @@ -15143,6 +15144,7 @@ assert((!E || isa<DeclRefExpr>(E) || isa<MemberExpr>(E)) && "Invalid Expr argument to DoMarkVarDeclReferenced"); Var->setReferenced(); + SemaRef.MarkUsingReferenced(Var, /*CXXScopeSpec*=*/nullptr, E); TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind(); @@ -15275,7 +15277,8 @@ return; } - SemaRef.MarkAnyDeclReferenced(Loc, D, MightBeOdrUse); + SemaRef.MarkAnyDeclReferenced(Loc, D, MightBeOdrUse, + /*CXXScopeSpec*=*/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. @@ -15296,7 +15299,8 @@ CXXMethodDecl *DM = MD->getDevirtualizedMethod( ME->getBase(), SemaRef.getLangOpts().AppleKext); if (DM) - SemaRef.MarkAnyDeclReferenced(Loc, DM, MightBeOdrUse); + SemaRef.MarkAnyDeclReferenced(Loc, DM, MightBeOdrUse, + /*CXXScopeSpec*=*/nullptr, E); } /// Perform reference-marking and odr-use handling for a DeclRefExpr. @@ -15336,18 +15340,20 @@ /// 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<VarDecl>(D)) { MarkVariableReferenced(Loc, VD); return; } } if (auto *FD = dyn_cast<FunctionDecl>(D)) { - MarkFunctionReferenced(Loc, FD, MightBeOdrUse); + MarkFunctionReferenced(Loc, FD, MightBeOdrUse, E); return; } D->setReferenced(); + MarkUsingReferenced(D, SS, E); } namespace { Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -3880,7 +3880,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); 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<ObjCInterfaceDecl>(IIDecl)) { (void)DiagnoseUseOfDecl(IDecl, NameLoc); if (!HasTrailingDot) @@ -1091,7 +1091,7 @@ NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl(); if (TypeDecl *Type = dyn_cast<TypeDecl>(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/SemaCXXScopeSpec.cpp =================================================================== --- lib/Sema/SemaCXXScopeSpec.cpp +++ lib/Sema/SemaCXXScopeSpec.cpp @@ -694,7 +694,7 @@ } if (auto *TD = dyn_cast_or_null<TypedefNameDecl>(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/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -1873,3 +1873,63 @@ return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), FnName, OpenCLDeclExtMap, 1, D.getSourceRange()); } + +// Mark the alias declaration and any associated chain as referenced. +void Sema::MarkNamespaceAliasReferenced(NamedDecl *ND) { + if (ND && !ND->isReferenced()) { + NamespaceAliasDecl *NA = nullptr; + while ((NA = dyn_cast<NamespaceAliasDecl>(ND)) && !NA->isReferenced()) { + NA->setReferenced(); + ND = NA->getAliasedNamespace(); + if (auto *NNS = NA->getQualifier()) + MarkNamespaceAliasReferenced(NNS->getAsNamespaceAlias()); + } + } +} + +/// \brief Mark as referenced any 'using declaration' that have introduced +/// the given declaration in the current context. +void Sema::MarkUsingReferenced(Decl *D, CXXScopeSpec *SS, Expr *E) { + // If the declaration is defined in a namespace, check if it was + // introduced in the currect context via any 'using' statement: + // using declaration, using directive or namespace alias. + auto *DC = D->getDeclContext(); + if (!DC->isNamespace()) + return; + + // The presence of a nested-name-specifier, means the namespace reference + // is being accessed explicitly or via a namespace alias. + if (auto *NNS = SS ? SS->getScopeRep() + : E ? dyn_cast<DeclRefExpr>(E)->getQualifier() + : nullptr) { + MarkNamespaceAliasReferenced(NNS->getAsNamespaceAlias()); + return; + } + + // Traverse scope hierarchy, looking for the given declaration. + for (auto *S = getCurScope(); S; S = S->getParent()) { + + // Check if the declaration was introduced by a 'using-declaration'. + UsingShadowDecl *USD = nullptr; + for (auto *DR : S->decls()) + if ((USD = dyn_cast<UsingShadowDecl>(DR)) && !USD->isReferenced()) { + if (USD->getTargetDecl() == D) { + USD->setReferenced(); + auto *UD = USD->getUsingDecl(); + UD->setReferenced(); + if (auto *NNS = UD->getQualifier()) + MarkNamespaceAliasReferenced(NNS->getAsNamespaceAlias()); + return; + } + } + + // Check if the declaration was introduced by a 'using-directive'. + auto *Target = dyn_cast<NamespaceDecl>(DC); + for (auto *UD : S->using_directives()) + if (!UD->isReferenced() && (UD->getNominatedNamespace() == Target)) { + UD->setReferenced(); + MarkNamespaceAliasReferenced(UD->getNominatedNamespaceAsWritten()); + return; + } + } +} Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -4010,16 +4010,21 @@ // 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); void UpdateMarkingForLValueToRValue(Expr *E); void CleanupVarDeclMarking(); + void MarkNamespaceAliasReferenced(NamedDecl *ND); + void MarkUsingReferenced(Decl *D, CXXScopeSpec *SS = nullptr, + Expr *E = nullptr); + enum TryCaptureKind { TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef };
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits