summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-07-14 23:14:12 +0000
committerDouglas Gregor <dgregor@apple.com>2010-07-14 23:14:12 +0000
commit5f0e252f635ab98060f6eb8e51babf6767064a8d (patch)
treee1bb1852ebbd977f2ce1fda248b614880464f970
parent25e72a892019026b06677aa6100065354b6fa451 (diff)
downloadbcm5719-llvm-5f0e252f635ab98060f6eb8e51babf6767064a8d.tar.gz
bcm5719-llvm-5f0e252f635ab98060f6eb8e51babf6767064a8d.zip
When there are extra or missing template parameter lists in a template
definition, we're likely going to end up breaking the invariants of the template system, e.g., that the depths of template parameter lists match up with the nesting template of the template. So, make sure we mark such ill-formed declarations as invalid or don't even build them at all. llvm-svn: 108372
-rw-r--r--clang/lib/Sema/Sema.h3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp24
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp19
-rw-r--r--clang/test/SemaTemplate/deduction-crash.cpp59
4 files changed, 96 insertions, 9 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index d902dfea1f1..8336918c134 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -2956,7 +2956,8 @@ public:
TemplateParameterList **ParamLists,
unsigned NumParamLists,
bool IsFriend,
- bool &IsExplicitSpecialization);
+ bool &IsExplicitSpecialization,
+ bool &Invalid);
DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, CXXScopeSpec &SS,
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9c683f726af..c1c898fac5f 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2572,6 +2572,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// determine whether we have a template or a template specialization.
bool isExplicitSpecialization = false;
unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
+ bool Invalid = false;
if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getSourceRange().getBegin(),
@@ -2579,7 +2580,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
(TemplateParameterList**)TemplateParamLists.get(),
TemplateParamLists.size(),
/*never a friend*/ false,
- isExplicitSpecialization)) {
+ isExplicitSpecialization,
+ Invalid)) {
// All but one template parameter lists have been matching.
--NumMatchedTemplateParamLists;
@@ -2606,7 +2608,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
VarDecl *NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
II, R, TInfo, SC, SCAsWritten);
- if (D.isInvalidType())
+ if (D.isInvalidType() || Invalid)
NewVD->setInvalidDecl();
SetNestedNameSpecifier(NewVD, D);
@@ -3156,6 +3158,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
bool isExplicitSpecialization = false;
bool isFunctionTemplateSpecialization = false;
unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
+ bool Invalid = false;
if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getSourceRange().getBegin(),
@@ -3163,7 +3166,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
(TemplateParameterList**)TemplateParamLists.get(),
TemplateParamLists.size(),
isFriend,
- isExplicitSpecialization)) {
+ isExplicitSpecialization,
+ Invalid)) {
// All but one template parameter lists have been matching.
--NumMatchedTemplateParamLists;
@@ -3214,6 +3218,12 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
(TemplateParameterList**)TemplateParamLists.release());
}
+ if (Invalid) {
+ NewFD->setInvalidDecl();
+ if (FunctionTemplate)
+ FunctionTemplate->setInvalidDecl();
+ }
+
// C++ [dcl.fct.spec]p5:
// The virtual specifier shall only be used in declarations of
// nonstatic class member functions that appear within a
@@ -5037,19 +5047,24 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// FIXME: Check explicit specializations more carefully.
bool isExplicitSpecialization = false;
unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
+ bool Invalid = false;
if (TUK != TUK_Reference) {
if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
(TemplateParameterList**)TemplateParameterLists.get(),
TemplateParameterLists.size(),
TUK == TUK_Friend,
- isExplicitSpecialization)) {
+ isExplicitSpecialization,
+ Invalid)) {
// All but one template parameter lists have been matching.
--NumMatchedTemplateParamLists;
if (TemplateParams->size() > 0) {
// This is a declaration or definition of a class template (which may
// be a member of another template).
+ if (Invalid)
+ return DeclPtrTy();
+
OwnedDecl = false;
DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
SS, Name, NameLoc, Attr,
@@ -5069,7 +5084,6 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
DeclContext *SearchDC = CurContext;
DeclContext *DC = CurContext;
bool isStdBadAlloc = false;
- bool Invalid = false;
RedeclarationKind Redecl = ForRedeclaration;
if (TUK == TUK_Friend || TUK == TUK_Reference)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 7cc43178450..f121954eed6 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1233,7 +1233,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
TemplateParameterList **ParamLists,
unsigned NumParamLists,
bool IsFriend,
- bool &IsExplicitSpecialization) {
+ bool &IsExplicitSpecialization,
+ bool &Invalid) {
IsExplicitSpecialization = false;
// Find the template-ids that occur within the nested-name-specifier. These
@@ -1311,6 +1312,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
diag::err_template_spec_needs_template_parameters)
<< TemplateId
<< SS.getRange();
+ Invalid = true;
} else {
Diag(SS.getRange().getBegin(), diag::err_template_spec_needs_header)
<< SS.getRange()
@@ -1373,7 +1375,13 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
<< ExplicitSpecializationsInSpecifier.back();
ExplicitSpecializationsInSpecifier.pop_back();
}
-
+
+ // We have a template parameter list with no corresponding scope, which
+ // means that the resulting template declaration can't be instantiated
+ // properly (we'll end up with dependent nodes when we shouldn't).
+ if (!isExplicitSpecHeader)
+ Invalid = true;
+
++Idx;
}
}
@@ -3622,12 +3630,17 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// template.
// FIXME: We probably shouldn't complain about these headers for
// friend declarations.
+ bool Invalid = false;
TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, SS,
(TemplateParameterList**)TemplateParameterLists.get(),
TemplateParameterLists.size(),
TUK == TUK_Friend,
- isExplicitSpecialization);
+ isExplicitSpecialization,
+ Invalid);
+ if (Invalid)
+ return true;
+
unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
if (TemplateParams)
--NumMatchedTemplateParamLists;
diff --git a/clang/test/SemaTemplate/deduction-crash.cpp b/clang/test/SemaTemplate/deduction-crash.cpp
new file mode 100644
index 00000000000..1860c7577c7
--- /dev/null
+++ b/clang/test/SemaTemplate/deduction-crash.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -fsyntax-only %s 2>&1| FileCheck %s
+
+// PR7511
+
+// Note that the error count below doesn't matter. We just want to
+// make sure that the parser doesn't crash.
+// CHECK: 16 errors
+template<a>
+struct int_;
+
+template<a>
+template<int,typename T1,typename>
+struct ac
+{
+ typedef T1 ae
+};
+
+template<class>struct aaa
+{
+ typedef ac<1,int,int>::ae ae
+};
+
+template<class>
+struct state_machine
+{
+ typedef aaa<int>::ae aaa;
+ int start()
+ {
+ ant(0);
+ }
+
+ template<class>
+ struct region_processing_helper
+ {
+ template<class,int=0>
+ struct In;
+
+ template<int my>
+ struct In<a::int_<aaa::a>,my>;
+
+ template<class Event>
+ int process(Event)
+ {
+ In<a::int_<0> > a;
+ }
+ }
+ template<class Event>
+ int ant(Event)
+ {
+ region_processing_helper<int>* helper;
+ helper->process(0)
+ }
+};
+
+int a()
+{
+ state_machine<int> p;
+ p.ant(0);
+}
OpenPOWER on IntegriCloud