summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerge Pavlov <sepavloff@gmail.com>2016-06-10 04:39:07 +0000
committerSerge Pavlov <sepavloff@gmail.com>2016-06-10 04:39:07 +0000
commite50bf75196e4145ed88e58f92fc8387e9d85b9fa (patch)
tree082009c749b6bccede003ecf335aeb33b90344bd
parentb52765c5a44db1816ad4e448e2e4c4445e496121 (diff)
downloadbcm5719-llvm-e50bf75196e4145ed88e58f92fc8387e9d85b9fa.tar.gz
bcm5719-llvm-e50bf75196e4145ed88e58f92fc8387e9d85b9fa.zip
Fix recognition of shadowed template parameter
Crash reported in PR28023 is caused by the fact that non-type template parameters are found by tag name lookup. In the code provided in that PR: template<int V> struct A { struct B { template <int> friend struct V; }; }; the template parameter V is found when lookup for redeclarations of 'struct V' is made. Latter on the error about shadowing of 'V' is emitted but the semantic context of 'struct V' is already determined wrong: 'struct A' instead of translation unit. The fix moves the check for shadowing toward the beginning of the method and thus prevents from wrong context calculations. This change fixes PR28023. llvm-svn: 272366
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp14
-rw-r--r--clang/test/CXX/temp/temp.res/temp.local/p6.cpp21
2 files changed, 24 insertions, 11 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 73b5c44b599..2ea242fc956 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -929,6 +929,13 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (Previous.begin() != Previous.end())
PrevDecl = (*Previous.begin())->getUnderlyingDecl();
+ if (PrevDecl && PrevDecl->isTemplateParameter()) {
+ // Maybe we will complain about the shadowed template parameter.
+ DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
+ // Just pretend that we didn't see the previous declaration.
+ PrevDecl = nullptr;
+ }
+
// If there is a previous declaration with the same name, check
// whether this is a valid redeclaration.
ClassTemplateDecl *PrevClassTemplate
@@ -1054,12 +1061,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// definition, as part of error recovery?
return true;
}
- }
- } else if (PrevDecl && PrevDecl->isTemplateParameter()) {
- // Maybe we will complain about the shadowed template parameter.
- DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
- // Just pretend that we didn't see the previous declaration.
- PrevDecl = nullptr;
+ }
} else if (PrevDecl) {
// C++ [temp]p5:
// A class template shall not have the same name as any other
diff --git a/clang/test/CXX/temp/temp.res/temp.local/p6.cpp b/clang/test/CXX/temp/temp.res/temp.local/p6.cpp
index 843b45543fc..e2aa0ff3442 100644
--- a/clang/test/CXX/temp/temp.res/temp.local/p6.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.local/p6.cpp
@@ -5,11 +5,11 @@ namespace N {}
template<typename T, // expected-note {{declared here}}
typename T> struct X {}; // expected-error {{declaration of 'T' shadows template parameter}}
-template<typename T> struct Y { // expected-note 17{{declared here}}
+template<typename T> struct Y { // expected-note 18{{declared here}}
template<typename T> struct A {}; // expected-error {{declaration of 'T' shadows template parameter}}
struct B {
- template<typename> struct T {}; // FIXME: desired-error {{declaration of 'T' shadows template parameter}}
+ template<typename> struct T {}; // expected-error {{declaration of 'T' shadows template parameter}}
};
struct C {
template<typename> void T(); // expected-error {{declaration of 'T' shadows template parameter}}
@@ -65,11 +65,11 @@ template<typename T> struct Y { // expected-note 17{{declared here}}
friend struct T; // expected-error {{declaration of 'T' shadows template parameter}}
};
-template<int T> struct Z { // expected-note 15{{declared here}}
+template<int T> struct Z { // expected-note 16{{declared here}}
template<typename T> struct A {}; // expected-error {{declaration of 'T' shadows template parameter}}
struct B {
- template<typename> struct T {}; // FIXME: desired-error {{declaration of 'T' shadows template parameter}}
+ template<typename> struct T {}; // expected-error {{declaration of 'T' shadows template parameter}}
};
struct C {
template<typename> void T(); // expected-error {{declaration of 'T' shadows template parameter}}
@@ -129,7 +129,8 @@ void f(int T) {} // expected-error {{declaration of 'T' shadows template paramet
// FIXME: These are ill-formed: a template-parameter shall not have the same name as the template name.
namespace A {
- template<typename T> struct T {};
+ template<typename T> struct T {}; // expected-error{{declaration of 'T' shadows template parameter}}
+ // expected-note@-1{{template parameter is declared here}}
}
namespace B {
template<typename T> void T() {}
@@ -137,3 +138,13 @@ namespace B {
namespace C {
template<typename T> int T;
}
+
+namespace PR28023 {
+template<int V> // expected-note{{template parameter is declared here}}
+struct A {
+ struct B {
+ template <int> friend struct V; // expected-error{{declaration of 'V' shadows template parameter}}
+ };
+};
+A<0>::B a;
+}
OpenPOWER on IntegriCloud