aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2010-09-03 21:12:34 +0000
committerChandler Carruth <chandlerc@gmail.com>2010-09-03 21:12:34 +0000
commit17fb855280be411389361f1c79753e0013c4187c (patch)
treefbf84b9e0fe9e6f83e95048bffba49c5a7993097 /lib/Sema/SemaTemplate.cpp
parent9c20fa9d46645480872f239a2fc631996ba7dc23 (diff)
Allow anonymous and local types. The support was already in place for these,
but this makes them work even as an extension in C++98. This resolves PR8077. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113011 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r--lib/Sema/SemaTemplate.cpp44
1 files changed, 23 insertions, 21 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 3c6ecaa53e..0fc83927b7 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2347,31 +2347,33 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
assert(ArgInfo && "invalid TypeSourceInfo");
QualType Arg = ArgInfo->getType();
- // C++ [temp.arg.type]p2:
+ // C++03 [temp.arg.type]p2:
// A local type, a type with no linkage, an unnamed type or a type
// compounded from any of these types shall not be used as a
// template-argument for a template type-parameter.
- //
- // FIXME: Perform the unnamed type check.
+ // C++0x allows these, and even in C++03 we allow them as an extension with
+ // a warning.
SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
- const TagType *Tag = 0;
- if (const EnumType *EnumT = Arg->getAs<EnumType>())
- Tag = EnumT;
- else if (const RecordType *RecordT = Arg->getAs<RecordType>())
- Tag = RecordT;
- if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod()) {
- SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
- return Diag(SR.getBegin(), diag::err_template_arg_local_type)
- << QualType(Tag, 0) << SR;
- } else if (Tag && !Tag->getDecl()->getDeclName() &&
- !Tag->getDecl()->getTypedefForAnonDecl()) {
- Diag(SR.getBegin(), diag::err_template_arg_unnamed_type) << SR;
- Diag(Tag->getDecl()->getLocation(), diag::note_template_unnamed_type_here);
- return true;
- } else if (Arg->isVariablyModifiedType()) {
- Diag(SR.getBegin(), diag::err_variably_modified_template_arg)
- << Arg;
- return true;
+ if (!LangOpts.CPlusPlus0x) {
+ const TagType *Tag = 0;
+ if (const EnumType *EnumT = Arg->getAs<EnumType>())
+ Tag = EnumT;
+ else if (const RecordType *RecordT = Arg->getAs<RecordType>())
+ Tag = RecordT;
+ if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod()) {
+ SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
+ Diag(SR.getBegin(), diag::ext_template_arg_local_type)
+ << QualType(Tag, 0) << SR;
+ } else if (Tag && !Tag->getDecl()->getDeclName() &&
+ !Tag->getDecl()->getTypedefForAnonDecl()) {
+ Diag(SR.getBegin(), diag::ext_template_arg_unnamed_type) << SR;
+ Diag(Tag->getDecl()->getLocation(),
+ diag::note_template_unnamed_type_here);
+ }
+ }
+
+ if (Arg->isVariablyModifiedType()) {
+ return Diag(SR.getBegin(), diag::err_variably_modified_template_arg) << Arg;
} else if (Context.hasSameUnqualifiedType(Arg, Context.OverloadTy)) {
return Diag(SR.getBegin(), diag::err_template_arg_overload_type) << SR;
}