aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-12-16 00:46:58 +0000
committerDouglas Gregor <dgregor@apple.com>2010-12-16 00:46:58 +0000
commit56c04588ef3cfa1bbc968fd68de2480a4e66971d (patch)
treea173c0b5da0ca60b5b2d40d7e8eb49674e7fac27
parent0c9e4799fd78d350a037498b2c797f2b2558791c (diff)
Check for unexpanded parameter packs in using declarations. As a
drive-by, make sure to check for unexpanded parameter packs within the name of a declaration. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121930 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td12
-rw-r--r--include/clang/Sema/Sema.h25
-rw-r--r--lib/Sema/SemaDecl.cpp3
-rw-r--r--lib/Sema/SemaDeclCXX.cpp5
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp52
-rw-r--r--test/CXX/temp/temp.decls/temp.variadic/p5.cpp9
6 files changed, 97 insertions, 9 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index f6e6f075b6..e9617a2f11 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1823,19 +1823,23 @@ def note_template_parameter_pack_here : Note<
def err_unexpanded_parameter_pack_0 : Error<
"%select{expression|base type|declaration type|data member type|bit-field "
- "size|static assertion|fixed underlying type|enumerator value}0 "
+ "size|static assertion|fixed underlying type|enumerator value|"
+ "using declaration}0 "
"contains an unexpanded parameter pack">;
def err_unexpanded_parameter_pack_1 : Error<
"%select{expression|base type|declaration type|data member type|bit-field "
- "size|static assertion|fixed underlying type|enumerator value}0 "
+ "size|static assertion|fixed underlying type|enumerator value|"
+ "using declaration}0 "
"contains unexpanded parameter pack %1">;
def err_unexpanded_parameter_pack_2 : Error<
"%select{expression|base type|declaration type|data member type|bit-field "
- "size|static assertion|fixed underlying type|enumerator value}0 "
+ "size|static assertion|fixed underlying type|enumerator value|"
+ "using declaration}0 "
"contains unexpanded parameter packs %1 and %2">;
def err_unexpanded_parameter_pack_3_or_more : Error<
"%select{expression|base type|declaration type|data member type|bit-field "
- "size|static assertion|fixed underlying type|enumerator value}0 "
+ "size|static assertion|fixed underlying type|enumerator value|"
+ "using declaration}0 "
"contains unexpanded parameter packs %1, %2, ...">;
def err_unexpected_typedef : Error<
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index c375b84808..c48f40403c 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -3157,7 +3157,10 @@ public:
UPPC_FixedUnderlyingType,
/// \brief The enumerator value.
- UPPC_EnumeratorValue
+ UPPC_EnumeratorValue,
+
+ /// \brief A using declaration.
+ UPPC_UsingDeclaration
};
/// \brief If the given type contains an unexpanded parameter pack,
@@ -3182,6 +3185,26 @@ public:
bool DiagnoseUnexpandedParameterPack(Expr *E,
UnexpandedParameterPackContext UPPC = UPPC_Expression);
+ /// \brief If the given nested-name-specifier contains an unexpanded
+ /// parameter pack, diagnose the error.
+ ///
+ /// \param SS The nested-name-specifier that is being checked for
+ /// unexpanded parameter packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
+ UnexpandedParameterPackContext UPPC);
+
+ /// \brief If the given name contains an unexpanded parameter pack,
+ /// diagnose the error.
+ ///
+ /// \param NameInfo The name (with source location information) that
+ /// is being checked for unexpanded parameter packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
+ UnexpandedParameterPackContext UPPC);
+
/// \brief Describes the result of template argument deduction.
///
/// The TemplateDeductionResult enumeration describes the result of
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 95c3b99801..c3384a5162 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2319,7 +2319,8 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
diag::err_declarator_need_ident)
<< D.getDeclSpec().getSourceRange() << D.getSourceRange();
return 0;
- }
+ } else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType))
+ return 0;
// The scope passed in may not be a decl scope. Zip up the scope tree until
// we find one that is.
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 555f5fd424..4a9abec583 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -928,6 +928,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
}
// FIXME: Check for template parameters!
+ // FIXME: Check that the name is an identifier!
Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
AS);
assert(Member && "HandleField never returns null");
@@ -3547,6 +3548,10 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
<< FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
}
+ if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) ||
+ DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration))
+ return 0;
+
NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
TargetNameInfo, AttrList,
/* IsInstantiation */ false,
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 057792914b..2338b5bfbc 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -171,7 +171,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
}
bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
- UnexpandedParameterPackContext UPPC) {
+ UnexpandedParameterPackContext UPPC) {
// C++0x [temp.variadic]p5:
// An appearance of a name of a parameter pack that is not expanded is
// ill-formed.
@@ -184,3 +184,53 @@ bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
DiagnoseUnexpandedParameterPacks(*this, E->getLocStart(), UPPC, Unexpanded);
return true;
}
+
+bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
+ UnexpandedParameterPackContext UPPC) {
+ // C++0x [temp.variadic]p5:
+ // An appearance of a name of a parameter pack that is not expanded is
+ // ill-formed.
+ if (!SS.getScopeRep() ||
+ !SS.getScopeRep()->containsUnexpandedParameterPack())
+ return false;
+
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ CollectUnexpandedParameterPacksVisitor(Unexpanded)
+ .TraverseNestedNameSpecifier(SS.getScopeRep());
+ assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+ DiagnoseUnexpandedParameterPacks(*this, SS.getRange().getBegin(),
+ UPPC, Unexpanded);
+ return true;
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
+ UnexpandedParameterPackContext UPPC) {
+ // C++0x [temp.variadic]p5:
+ // An appearance of a name of a parameter pack that is not expanded is
+ // ill-formed.
+ switch (NameInfo.getName().getNameKind()) {
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXOperatorName:
+ case DeclarationName::CXXLiteralOperatorName:
+ case DeclarationName::CXXUsingDirective:
+ return false;
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ if (!NameInfo.getNamedTypeInfo()->getType()
+ ->containsUnexpandedParameterPack())
+ return false;
+ break;
+ }
+
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ CollectUnexpandedParameterPacksVisitor(Unexpanded)
+ .TraverseTypeLoc(NameInfo.getNamedTypeInfo()->getTypeLoc());
+ assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+ DiagnoseUnexpandedParameterPacks(*this, NameInfo.getLoc(), UPPC, Unexpanded);
+ return true;
+}
diff --git a/test/CXX/temp/temp.decls/temp.variadic/p5.cpp b/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
index 1f56c889a6..a1c07c96fe 100644
--- a/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
+++ b/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
@@ -104,10 +104,11 @@ void TestPPNameFunc(int i) {
}
// FIXME: Test for unexpanded parameter packs in declarations.
-template<typename... Types>
-struct TestUnexpandedDecls {
+template<typename T, typename... Types>
+struct TestUnexpandedDecls : T{
void member_function(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}}
void member_function () throw(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}}
+ operator Types() const; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}}
Types data_member; // expected-error{{data member type contains unexpanded parameter pack 'Types'}}
static Types static_data_member; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}}
unsigned bit_field : static_cast<Types>(0); // expected-error{{bit-field size contains unexpanded parameter pack 'Types'}}
@@ -116,6 +117,10 @@ struct TestUnexpandedDecls {
enum E0 : Types { // expected-error{{fixed underlying type contains unexpanded parameter pack 'Types'}}
EnumValue = static_cast<Types>(0) // expected-error{{enumerator value contains unexpanded parameter pack 'Types'}}
};
+
+ using typename Types::type; // expected-error{{using declaration contains unexpanded parameter pack 'Types'}}
+ using Types::value; // expected-error{{using declaration contains unexpanded parameter pack 'Types'}}
+ using T::operator Types; // expected-error{{using declaration contains unexpanded parameter pack 'Types'}}
};
// Test for diagnostics in the presence of multiple unexpanded