aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2012-08-15 20:02:54 +0000
committerDimitry Andric <dim@FreeBSD.org>2012-08-15 20:02:54 +0000
commit56d91b49b13fe55c918afbda19f6165b5fbff87a (patch)
tree9abb1a658a297776086f4e0dfa6ca533de02104e /lib/Sema/SemaTemplate.cpp
parent41e20f564abdb05101d6b2b29c59459a966c22cc (diff)
downloadsrc-56d91b49b13fe55c918afbda19f6165b5fbff87a.tar.gz
src-56d91b49b13fe55c918afbda19f6165b5fbff87a.zip
Vendor import of clang trunk r161861:vendor/clang/clang-trunk-r161861
Notes
Notes: svn path=/vendor/clang/dist/; revision=239313 svn path=/vendor/clang/clang-trunk-r161861/; revision=239314; tag=vendor/clang/clang-trunk-r161861
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r--lib/Sema/SemaTemplate.cpp238
1 files changed, 190 insertions, 48 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 51ce2a1345a5..c8e45016671d 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -354,12 +354,14 @@ void Sema::LookupTemplateName(LookupResult &Found,
return;
}
- if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope) {
- // C++ [basic.lookup.classref]p1:
+ if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope &&
+ !(getLangOpts().CPlusPlus0x && !Found.empty())) {
+ // C++03 [basic.lookup.classref]p1:
// [...] If the lookup in the class of the object expression finds a
// template, the name is also looked up in the context of the entire
// postfix-expression and [...]
//
+ // Note: C++11 does not perform this second lookup.
LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(),
LookupOrdinaryName);
LookupName(FoundOuter, S);
@@ -743,7 +745,7 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
}
/// ActOnTemplateTemplateParameter - Called when a C++ template template
-/// parameter (e.g. T in template <template <typename> class T> class array)
+/// parameter (e.g. T in template <template \<typename> class T> class array)
/// has been parsed. S is the current scope.
Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,
SourceLocation TmpLoc,
@@ -865,9 +867,13 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
return true;
}
- // Find any previous declaration with this name.
+ // Find any previous declaration with this name. For a friend with no
+ // scope explicitly specified, we only look for tag declarations (per
+ // C++11 [basic.lookup.elab]p2).
DeclContext *SemanticContext;
- LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName,
+ LookupResult Previous(*this, Name, NameLoc,
+ (SS.isEmpty() && TUK == TUK_Friend)
+ ? LookupTagName : LookupOrdinaryName,
ForRedeclaration);
if (SS.isNotEmpty() && !SS.isInvalid()) {
SemanticContext = computeDeclContext(SS, true);
@@ -893,7 +899,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
Invalid = true;
} else if (TUK != TUK_Friend && TUK != TUK_Reference)
diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc);
-
+
LookupQualifiedName(Previous, SemanticContext);
} else {
SemanticContext = CurContext;
@@ -948,22 +954,32 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// declaration.
PrevDecl = PrevClassTemplate = 0;
SemanticContext = OutermostContext;
- }
- }
- if (CurContext->isDependentContext()) {
- // If this is a dependent context, we don't want to link the friend
- // class template to the template in scope, because that would perform
- // checking of the template parameter lists that can't be performed
- // until the outer context is instantiated.
- PrevDecl = PrevClassTemplate = 0;
+ // Check that the chosen semantic context doesn't already contain a
+ // declaration of this name as a non-tag type.
+ LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName,
+ ForRedeclaration);
+ DeclContext *LookupContext = SemanticContext;
+ while (LookupContext->isTransparentContext())
+ LookupContext = LookupContext->getLookupParent();
+ LookupQualifiedName(Previous, LookupContext);
+
+ if (Previous.isAmbiguous())
+ return true;
+
+ if (Previous.begin() != Previous.end())
+ PrevDecl = (*Previous.begin())->getUnderlyingDecl();
+ }
}
} else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
PrevDecl = PrevClassTemplate = 0;
if (PrevClassTemplate) {
- // Ensure that the template parameter lists are compatible.
- if (!TemplateParameterListsAreEqual(TemplateParams,
+ // Ensure that the template parameter lists are compatible. Skip this check
+ // for a friend in a dependent context: the template parameter list itself
+ // could be dependent.
+ if (!(TUK == TUK_Friend && CurContext->isDependentContext()) &&
+ !TemplateParameterListsAreEqual(TemplateParams,
PrevClassTemplate->getTemplateParameters(),
/*Complain=*/true,
TPL_TemplateMatch))
@@ -1012,8 +1028,10 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Check the template parameter list of this declaration, possibly
// merging in the template parameter list from the previous class
- // template declaration.
- if (CheckTemplateParameterList(TemplateParams,
+ // template declaration. Skip this check for a friend in a dependent
+ // context, because the template parameter list might be dependent.
+ if (!(TUK == TUK_Friend && CurContext->isDependentContext()) &&
+ CheckTemplateParameterList(TemplateParams,
PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0,
(SS.isSet() && SemanticContext &&
SemanticContext->isRecord() &&
@@ -1025,9 +1043,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (SS.isSet()) {
// If the name of the template was qualified, we must be defining the
// template out-of-line.
- if (!SS.isInvalid() && !Invalid && !PrevClassTemplate &&
- !(TUK == TUK_Friend && CurContext->isDependentContext())) {
- Diag(NameLoc, diag::err_member_def_does_not_match)
+ if (!SS.isInvalid() && !Invalid && !PrevClassTemplate) {
+ Diag(NameLoc, TUK == TUK_Friend ? diag::err_friend_decl_does_not_match
+ : diag::err_member_def_does_not_match)
<< Name << SemanticContext << SS.getRange();
Invalid = true;
}
@@ -1046,8 +1064,10 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Add alignment attributes if necessary; these attributes are checked when
// the ASTContext lays out the structure.
- AddAlignmentAttributesForRecord(NewClass);
- AddMsStructLayoutForRecord(NewClass);
+ if (TUK == TUK_Definition) {
+ AddAlignmentAttributesForRecord(NewClass);
+ AddMsStructLayoutForRecord(NewClass);
+ }
ClassTemplateDecl *NewTemplate
= ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
@@ -1084,6 +1104,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (Attr)
ProcessDeclAttributeList(S, NewClass, Attr);
+ AddPushedVisibilityAttribute(NewClass);
+
if (TUK != TUK_Friend)
PushOnScopeChains(NewTemplate, S);
else {
@@ -1116,6 +1138,11 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
NewTemplate->setInvalidDecl();
NewClass->setInvalidDecl();
}
+ if (PrevClassTemplate)
+ mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl());
+
+ ActOnDocumentableDecl(NewTemplate);
+
return NewTemplate;
}
@@ -1972,6 +1999,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
TemplateArgLists.addOuterTemplateArguments(0, 0);
InstantiatingTemplate Inst(*this, TemplateLoc, Template);
+ if (Inst)
+ return QualType();
CanonType = SubstType(Pattern->getUnderlyingType(),
TemplateArgLists, AliasTemplate->getLocation(),
AliasTemplate->getDeclName());
@@ -2420,6 +2449,43 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
return true;
}
+ case TemplateArgument::Expression: {
+ // We have a template type parameter but the template argument is an
+ // expression; see if maybe it is missing the "typename" keyword.
+ CXXScopeSpec SS;
+ DeclarationNameInfo NameInfo;
+
+ if (DeclRefExpr *ArgExpr = dyn_cast<DeclRefExpr>(Arg.getAsExpr())) {
+ SS.Adopt(ArgExpr->getQualifierLoc());
+ NameInfo = ArgExpr->getNameInfo();
+ } else if (DependentScopeDeclRefExpr *ArgExpr =
+ dyn_cast<DependentScopeDeclRefExpr>(Arg.getAsExpr())) {
+ SS.Adopt(ArgExpr->getQualifierLoc());
+ NameInfo = ArgExpr->getNameInfo();
+ } else if (CXXDependentScopeMemberExpr *ArgExpr =
+ dyn_cast<CXXDependentScopeMemberExpr>(Arg.getAsExpr())) {
+ if (ArgExpr->isImplicitAccess()) {
+ SS.Adopt(ArgExpr->getQualifierLoc());
+ NameInfo = ArgExpr->getMemberNameInfo();
+ }
+ }
+
+ if (NameInfo.getName().isIdentifier()) {
+ LookupResult Result(*this, NameInfo, LookupOrdinaryName);
+ LookupParsedName(Result, CurScope, &SS);
+
+ if (Result.getAsSingle<TypeDecl>() ||
+ Result.getResultKind() ==
+ LookupResult::NotFoundInCurrentInstantiation) {
+ // FIXME: Add a FixIt and fix up the template argument for recovery.
+ SourceLocation Loc = AL.getSourceRange().getBegin();
+ Diag(Loc, diag::err_template_arg_must_be_type_suggest);
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+ }
+ // fallthrough
+ }
default: {
// We have a template type parameter but the template argument
// is not a type.
@@ -2492,9 +2558,10 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
= SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
- Template, Converted.data(),
- Converted.size(),
+ Template, Converted,
SourceRange(TemplateLoc, RAngleLoc));
+ if (Inst)
+ return 0;
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs,
@@ -2541,9 +2608,10 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
= SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
- Template, Converted.data(),
- Converted.size(),
+ Template, Converted,
SourceRange(TemplateLoc, RAngleLoc));
+ if (Inst)
+ return ExprError();
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
@@ -2590,9 +2658,10 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
= SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
- Template, Converted.data(),
- Converted.size(),
+ Template, Converted,
SourceRange(TemplateLoc, RAngleLoc));
+ if (Inst)
+ return TemplateName();
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
// Substitute into the nested-name-specifier first,
@@ -2724,8 +2793,10 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
!Template->getDeclContext()->isDependentContext()) {
// Do substitution on the type of the non-type template parameter.
InstantiatingTemplate Inst(*this, TemplateLoc, Template,
- NTTP, Converted.data(), Converted.size(),
+ NTTP, Converted,
SourceRange(TemplateLoc, RAngleLoc));
+ if (Inst)
+ return true;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
Converted.data(), Converted.size());
@@ -2856,8 +2927,10 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
// Set up a template instantiation context.
LocalInstantiationScope Scope(*this);
InstantiatingTemplate Inst(*this, TemplateLoc, Template,
- TempParm, Converted.data(), Converted.size(),
+ TempParm, Converted,
SourceRange(TemplateLoc, RAngleLoc));
+ if (Inst)
+ return true;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
Converted.data(), Converted.size());
@@ -3086,9 +3159,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// Introduce an instantiation record that describes where we are using
// the default template argument.
- InstantiatingTemplate Instantiating(*this, RAngleLoc, Template, *Param,
- Converted.data(), Converted.size(),
+ InstantiatingTemplate Instantiating(*this, RAngleLoc, Template,
+ *Param, Converted,
SourceRange(TemplateLoc, RAngleLoc));
+ if (Instantiating)
+ return true;
// Check the default template argument.
if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc,
@@ -3574,6 +3649,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
if (ParamType->isPointerType() || ParamType->isNullPtrType()) {
switch (isNullPointerValueTemplateArgument(S, Param, ParamType, Arg)) {
case NPV_NullPointer:
+ S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
Converted = TemplateArgument((Decl *)0);
return false;
@@ -3870,6 +3946,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
case NPV_Error:
return true;
case NPV_NullPointer:
+ S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
Converted = TemplateArgument((Decl *)0);
return false;
case NPV_NotNullPointer:
@@ -4066,7 +4143,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
IntegerType = Enum->getDecl()->getIntegerType();
Value = Value.extOrTrunc(Context.getTypeSize(IntegerType));
- Converted = TemplateArgument(Value, Context.getCanonicalType(ParamType));
+ Converted = TemplateArgument(Context, Value,
+ Context.getCanonicalType(ParamType));
return ArgResult;
}
@@ -4093,8 +4171,20 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Diag(Param->getLocation(), diag::note_template_param_here);
return ExprError();
} else if (!Arg->isValueDependent()) {
- Arg = VerifyIntegerConstantExpression(Arg, &Value,
- PDiag(diag::err_template_arg_not_ice) << ArgType, false).take();
+ class TmplArgICEDiagnoser : public VerifyICEDiagnoser {
+ QualType T;
+
+ public:
+ TmplArgICEDiagnoser(QualType T) : T(T) { }
+
+ virtual void diagnoseNotICE(Sema &S, SourceLocation Loc,
+ SourceRange SR) {
+ S.Diag(Loc, diag::err_template_arg_not_ice) << T << SR;
+ }
+ } Diagnoser(ArgType);
+
+ Arg = VerifyIntegerConstantExpression(Arg, &Value, Diagnoser,
+ false).take();
if (!Arg)
return ExprError();
}
@@ -4180,7 +4270,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
}
}
- Converted = TemplateArgument(Value,
+ Converted = TemplateArgument(Context, Value,
ParamType->isEnumeralType()
? Context.getCanonicalType(ParamType)
: IntegerType);
@@ -4305,6 +4395,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return ExprError();
case NPV_NullPointer:
+ Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
Converted = TemplateArgument((Decl *)0);
return Owned(Arg);;
}
@@ -4497,13 +4588,13 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
Kind = CharacterLiteral::Ascii;
return Owned(new (Context) CharacterLiteral(
- Arg.getAsIntegral()->getZExtValue(),
+ Arg.getAsIntegral().getZExtValue(),
Kind, T, Loc));
}
if (T->isBooleanType())
return Owned(new (Context) CXXBoolLiteralExpr(
- Arg.getAsIntegral()->getBoolValue(),
+ Arg.getAsIntegral().getBoolValue(),
T, Loc));
if (T->isNullPtrType())
@@ -4518,7 +4609,7 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
else
BT = T;
- Expr *E = IntegerLiteral::Create(Context, *Arg.getAsIntegral(), BT, Loc);
+ Expr *E = IntegerLiteral::Create(Context, Arg.getAsIntegral(), BT, Loc);
if (T->isEnumeralType()) {
// FIXME: This is a hack. We need a better way to handle substituted
// non-type template parameters.
@@ -5041,7 +5132,7 @@ static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S,
/// \param TemplateParams the template parameters of the primary class
/// template.
///
-/// \param TemplateArg the template arguments of the class template
+/// \param TemplateArgs the template arguments of the class template
/// partial specialization.
///
/// \returns true if there was an error, false otherwise.
@@ -5481,7 +5572,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Decl *Sema::ActOnTemplateDeclarator(Scope *S,
MultiTemplateParamsArg TemplateParameterLists,
Declarator &D) {
- return HandleDeclarator(S, D, move(TemplateParameterLists));
+ Decl *NewDecl = HandleDeclarator(S, D, move(TemplateParameterLists));
+ ActOnDocumentableDecl(NewDecl);
+ return NewDecl;
}
Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
@@ -5719,14 +5812,17 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
}
/// \brief Perform semantic analysis for the given dependent function
-/// template specialization. The only possible way to get a dependent
-/// function template specialization is with a friend declaration,
-/// like so:
+/// template specialization.
+///
+/// The only possible way to get a dependent function template specialization
+/// is with a friend declaration, like so:
///
-/// template <class T> void foo(T);
-/// template <class T> class A {
+/// \code
+/// template \<class T> void foo(T);
+/// template \<class T> class A {
/// friend void foo<>(T);
/// };
+/// \endcode
///
/// There really isn't any useful analysis we can do here, so we
/// just store the information.
@@ -6890,6 +6986,42 @@ Sema::ActOnTypenameType(Scope *S,
}
+/// Determine whether this failed name lookup should be treated as being
+/// disabled by a usage of std::enable_if.
+static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II,
+ SourceRange &CondRange) {
+ // We must be looking for a ::type...
+ if (!II.isStr("type"))
+ return false;
+
+ // ... within an explicitly-written template specialization...
+ if (!NNS || !NNS.getNestedNameSpecifier()->getAsType())
+ return false;
+ TypeLoc EnableIfTy = NNS.getTypeLoc();
+ TemplateSpecializationTypeLoc *EnableIfTSTLoc =
+ dyn_cast<TemplateSpecializationTypeLoc>(&EnableIfTy);
+ if (!EnableIfTSTLoc || EnableIfTSTLoc->getNumArgs() == 0)
+ return false;
+ const TemplateSpecializationType *EnableIfTST =
+ cast<TemplateSpecializationType>(EnableIfTSTLoc->getTypePtr());
+
+ // ... which names a complete class template declaration...
+ const TemplateDecl *EnableIfDecl =
+ EnableIfTST->getTemplateName().getAsTemplateDecl();
+ if (!EnableIfDecl || EnableIfTST->isIncompleteType())
+ return false;
+
+ // ... called "enable_if".
+ const IdentifierInfo *EnableIfII =
+ EnableIfDecl->getDeclName().getAsIdentifierInfo();
+ if (!EnableIfII || !EnableIfII->isStr("enable_if"))
+ return false;
+
+ // Assume the first template argument is the condition.
+ CondRange = EnableIfTSTLoc->getArgLoc(0).getSourceRange();
+ return true;
+}
+
/// \brief Build the type that describes a C++ typename specifier,
/// e.g., "typename T::type".
QualType
@@ -6926,9 +7058,19 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
unsigned DiagID = 0;
Decl *Referenced = 0;
switch (Result.getResultKind()) {
- case LookupResult::NotFound:
+ case LookupResult::NotFound: {
+ // If we're looking up 'type' within a template named 'enable_if', produce
+ // a more specific diagnostic.
+ SourceRange CondRange;
+ if (isEnableIf(QualifierLoc, II, CondRange)) {
+ Diag(CondRange.getBegin(), diag::err_typename_nested_not_found_enable_if)
+ << Ctx << CondRange;
+ return QualType();
+ }
+
DiagID = diag::err_typename_nested_not_found;
break;
+ }
case LookupResult::FoundUnresolvedValue: {
// We found a using declaration that is a value. Most likely, the using