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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits