forked from OSchip/llvm-project
parent
6c46216daf
commit
72caf2bb6b
|
@ -2782,7 +2782,7 @@ public:
|
|||
|
||||
/// \brief Return the next partial specialization sequence number.
|
||||
unsigned getNextPartialSpecSequenceNumber() {
|
||||
return getPartialSpecializations().size();
|
||||
return getCommonPtr()->PartialSpecializations.size();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the partial specializations as an ordered list.
|
||||
|
|
|
@ -1472,8 +1472,7 @@ public:
|
|||
MultiTemplateParamsArg TemplateParamLists,
|
||||
bool &AddToScope);
|
||||
// Returns true if the variable declaration is a redeclaration
|
||||
bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous,
|
||||
bool IsVariableTemplate = false);
|
||||
bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous);
|
||||
void CheckVariableDeclarationType(VarDecl *NewVD);
|
||||
void CheckCompleteVariableDeclaration(VarDecl *var);
|
||||
void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
|
||||
|
@ -1869,7 +1868,7 @@ public:
|
|||
Scope *S, bool MergeTypeWithOld);
|
||||
void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old);
|
||||
void MergeVarDecl(VarDecl *New, LookupResult &Previous,
|
||||
bool IsVariableTemplate, bool MergeTypeWithPrevious);
|
||||
bool MergeTypeWithPrevious);
|
||||
void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld);
|
||||
void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old);
|
||||
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S);
|
||||
|
@ -6432,7 +6431,7 @@ public:
|
|||
const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
LateInstantiatedAttrVec *LateAttrs = 0,
|
||||
LocalInstantiationScope *StartingScope = 0,
|
||||
bool ForVarTemplate = false);
|
||||
bool InstantiatingVarTemplate = false);
|
||||
void InstantiateVariableInitializer(
|
||||
VarDecl *Var, VarDecl *OldVar,
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||
|
|
|
@ -425,7 +425,7 @@ namespace clang {
|
|||
Decl *VisitFunctionDecl(FunctionDecl *D,
|
||||
TemplateParameterList *TemplateParams);
|
||||
Decl *VisitDecl(Decl *D);
|
||||
Decl *VisitVarDecl(VarDecl *D, bool ForVarTemplate);
|
||||
Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate);
|
||||
|
||||
// Enable late instantiation of attributes. Late instantiated attributes
|
||||
// will be stored in LA.
|
||||
|
|
|
@ -2887,7 +2887,7 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old,
|
|||
/// definitions here, since the initializer hasn't been attached.
|
||||
///
|
||||
void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous,
|
||||
bool IsVariableTemplate, bool MergeTypeWithPrevious) {
|
||||
bool MergeTypeWithPrevious) {
|
||||
// If the new decl is already invalid, don't do any other checking.
|
||||
if (New->isInvalidDecl())
|
||||
return;
|
||||
|
@ -2896,7 +2896,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous,
|
|||
VarDecl *Old = 0;
|
||||
if (Previous.isSingleResult() &&
|
||||
(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
|
||||
if (IsVariableTemplate)
|
||||
if (New->getDescribedVarTemplate())
|
||||
Old = Old->getDescribedVarTemplate() ? Old : 0;
|
||||
else
|
||||
Old = Old->getDescribedVarTemplate() ? 0 : Old;
|
||||
|
@ -3039,6 +3039,11 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous,
|
|||
|
||||
// Inherit access appropriately.
|
||||
New->setAccess(Old->getAccess());
|
||||
|
||||
if (VarTemplateDecl *VTD = New->getDescribedVarTemplate()) {
|
||||
if (New->isStaticDataMember() && New->isOutOfLine())
|
||||
VTD->setAccess(New->getAccess());
|
||||
}
|
||||
}
|
||||
|
||||
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
|
||||
|
@ -4893,10 +4898,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
bool IsVariableTemplateSpecialization = false;
|
||||
bool IsPartialSpecialization = false;
|
||||
bool IsVariableTemplate = false;
|
||||
bool Invalid = false; // TODO: Can we remove this (error-prone)?
|
||||
TemplateParameterList *TemplateParams = 0;
|
||||
VarTemplateDecl *PrevVarTemplate = 0;
|
||||
VarDecl *NewVD;
|
||||
VarDecl *NewVD = 0;
|
||||
VarTemplateDecl *NewTemplate = 0;
|
||||
if (!getLangOpts().CPlusPlus) {
|
||||
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
|
||||
D.getIdentifierLoc(), II,
|
||||
|
@ -4905,6 +4909,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
if (D.isInvalidType())
|
||||
NewVD->setInvalidDecl();
|
||||
} else {
|
||||
bool Invalid = false;
|
||||
|
||||
if (DC->isRecord() && !CurContext->isRecord()) {
|
||||
// This is an out-of-line definition of a static data member.
|
||||
switch (SC) {
|
||||
|
@ -4963,10 +4969,11 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
|
||||
// Match up the template parameter lists with the scope specifier, then
|
||||
// determine whether we have a template or a template specialization.
|
||||
TemplateParams = MatchTemplateParametersToScopeSpecifier(
|
||||
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
|
||||
D.getCXXScopeSpec(), TemplateParamLists,
|
||||
/*never a friend*/ false, IsExplicitSpecialization, Invalid);
|
||||
TemplateParameterList *TemplateParams =
|
||||
MatchTemplateParametersToScopeSpecifier(
|
||||
D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
|
||||
D.getCXXScopeSpec(), TemplateParamLists,
|
||||
/*never a friend*/ false, IsExplicitSpecialization, Invalid);
|
||||
if (TemplateParams) {
|
||||
if (!TemplateParams->size() &&
|
||||
D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
|
||||
|
@ -5090,13 +5097,24 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
|
||||
D.getIdentifierLoc(), II, R, TInfo, SC);
|
||||
|
||||
// If this is supposed to be a variable template, create it as such.
|
||||
if (IsVariableTemplate) {
|
||||
NewTemplate =
|
||||
VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name,
|
||||
TemplateParams, NewVD, PrevVarTemplate);
|
||||
NewVD->setDescribedVarTemplate(NewTemplate);
|
||||
}
|
||||
|
||||
// If this decl has an auto type in need of deduction, make a note of the
|
||||
// Decl so we can diagnose uses of it in its own initializer.
|
||||
if (D.getDeclSpec().containsPlaceholderType() && R->getContainedAutoType())
|
||||
ParsingInitForAutoVars.insert(NewVD);
|
||||
|
||||
if (D.isInvalidType() || Invalid)
|
||||
if (D.isInvalidType() || Invalid) {
|
||||
NewVD->setInvalidDecl();
|
||||
if (NewTemplate)
|
||||
NewTemplate->setInvalidDecl();
|
||||
}
|
||||
|
||||
SetNestedNameSpecifier(NewVD, D);
|
||||
|
||||
|
@ -5120,6 +5138,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
// Set the lexical context. If the declarator has a C++ scope specifier, the
|
||||
// lexical context will be different from the semantic context.
|
||||
NewVD->setLexicalDeclContext(CurContext);
|
||||
if (NewTemplate)
|
||||
NewTemplate->setLexicalDeclContext(CurContext);
|
||||
|
||||
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) {
|
||||
if (NewVD->hasLocalStorage()) {
|
||||
|
@ -5178,8 +5198,11 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
<< 0 << NewVD->getDeclName()
|
||||
<< SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
|
||||
<< FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
|
||||
else
|
||||
else {
|
||||
NewVD->setModulePrivate();
|
||||
if (NewTemplate)
|
||||
NewTemplate->setModulePrivate();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle attributes prior to checking for duplicates in MergeVarDecl
|
||||
|
@ -5238,7 +5261,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
}
|
||||
|
||||
// Diagnose shadowed variables before filtering for scope.
|
||||
// FIXME: Special treatment for static variable template members (?).
|
||||
if (!D.getCXXScopeSpec().isSet())
|
||||
CheckShadow(S, NewVD, Previous);
|
||||
|
||||
|
@ -5285,15 +5307,12 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
LookupResult PrevDecl(*this, GetNameForDeclarator(D),
|
||||
LookupOrdinaryName, ForRedeclaration);
|
||||
PrevDecl.addDecl(PrevVarTemplate->getTemplatedDecl());
|
||||
D.setRedeclaration(
|
||||
CheckVariableDeclaration(NewVD, PrevDecl, IsVariableTemplate));
|
||||
D.setRedeclaration(CheckVariableDeclaration(NewVD, PrevDecl));
|
||||
} else
|
||||
D.setRedeclaration(
|
||||
CheckVariableDeclaration(NewVD, Previous, IsVariableTemplate));
|
||||
D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
|
||||
}
|
||||
|
||||
// This is an explicit specialization of a static data member. Check it.
|
||||
// FIXME: Special treatment for static variable template members (?).
|
||||
if (IsExplicitSpecialization && !NewVD->isInvalidDecl() &&
|
||||
CheckMemberSpecialization(NewVD, Previous))
|
||||
NewVD->setInvalidDecl();
|
||||
|
@ -5317,40 +5336,17 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
}
|
||||
}
|
||||
|
||||
// If this is not a variable template, return it now.
|
||||
if (!IsVariableTemplate)
|
||||
return NewVD;
|
||||
|
||||
// If this is supposed to be a variable template, create it as such.
|
||||
VarTemplateDecl *NewTemplate =
|
||||
VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name,
|
||||
TemplateParams, NewVD, PrevVarTemplate);
|
||||
NewVD->setDescribedVarTemplate(NewTemplate);
|
||||
|
||||
if (D.getDeclSpec().isModulePrivateSpecified())
|
||||
NewTemplate->setModulePrivate();
|
||||
|
||||
// If we are providing an explicit specialization of a static variable
|
||||
// template, make a note of that.
|
||||
if (PrevVarTemplate && PrevVarTemplate->getInstantiatedFromMemberTemplate())
|
||||
PrevVarTemplate->setMemberSpecialization();
|
||||
|
||||
// Set the lexical context of this template
|
||||
NewTemplate->setLexicalDeclContext(CurContext);
|
||||
if (NewVD->isStaticDataMember() && NewVD->isOutOfLine())
|
||||
NewTemplate->setAccess(NewVD->getAccess());
|
||||
|
||||
PushOnScopeChains(NewTemplate, S);
|
||||
AddToScope = false;
|
||||
|
||||
if (Invalid) {
|
||||
NewTemplate->setInvalidDecl();
|
||||
NewVD->setInvalidDecl();
|
||||
if (NewTemplate) {
|
||||
ActOnDocumentableDecl(NewTemplate);
|
||||
return NewTemplate;
|
||||
}
|
||||
|
||||
ActOnDocumentableDecl(NewTemplate);
|
||||
|
||||
return NewTemplate;
|
||||
return NewVD;
|
||||
}
|
||||
|
||||
/// \brief Diagnose variable or built-in function shadowing. Implements
|
||||
|
@ -5716,9 +5712,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
|
|||
/// Sets NewVD->isInvalidDecl() if an error was encountered.
|
||||
///
|
||||
/// Returns true if the variable declaration is a redeclaration.
|
||||
bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
|
||||
LookupResult &Previous,
|
||||
bool IsVariableTemplate) {
|
||||
bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) {
|
||||
CheckVariableDeclarationType(NewVD);
|
||||
|
||||
// If the decl is already known invalid, don't check it.
|
||||
|
@ -5768,7 +5762,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
|
|||
filterNonConflictingPreviousDecls(Context, NewVD, Previous);
|
||||
|
||||
if (!Previous.empty()) {
|
||||
MergeVarDecl(NewVD, Previous, IsVariableTemplate, MergeTypeWithPrevious);
|
||||
MergeVarDecl(NewVD, Previous, MergeTypeWithPrevious);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -2254,12 +2254,10 @@ namespace {
|
|||
};
|
||||
}
|
||||
|
||||
bool
|
||||
Sema::InstantiateClassTemplateSpecialization(
|
||||
SourceLocation PointOfInstantiation,
|
||||
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
||||
TemplateSpecializationKind TSK,
|
||||
bool Complain) {
|
||||
bool Sema::InstantiateClassTemplateSpecialization(
|
||||
SourceLocation PointOfInstantiation,
|
||||
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
||||
TemplateSpecializationKind TSK, bool Complain) {
|
||||
// Perform the actual instantiation on the canonical declaration.
|
||||
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
|
||||
ClassTemplateSpec->getCanonicalDecl());
|
||||
|
|
|
@ -320,10 +320,11 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
|
|||
|
||||
// FIXME: Revise for static member templates.
|
||||
Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
|
||||
return VisitVarDecl(D, /*ForVarTemplate=*/false);
|
||||
return VisitVarDecl(D, /*InstantiatingVarTemplate=*/false);
|
||||
}
|
||||
|
||||
Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, bool ForVarTemplate) {
|
||||
Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
|
||||
bool InstantiatingVarTemplate) {
|
||||
|
||||
// If this is the variable for an anonymous struct or union,
|
||||
// instantiate the anonymous struct/union type first.
|
||||
|
@ -361,7 +362,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, bool ForVarTemplate) {
|
|||
return 0;
|
||||
|
||||
SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs,
|
||||
StartingScope, ForVarTemplate);
|
||||
StartingScope, InstantiatingVarTemplate);
|
||||
return Var;
|
||||
}
|
||||
|
||||
|
@ -971,7 +972,8 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) {
|
|||
}
|
||||
|
||||
VarDecl *VarInst =
|
||||
cast_or_null<VarDecl>(VisitVarDecl(Pattern, /*ForVarTemplate=*/ true));
|
||||
cast_or_null<VarDecl>(VisitVarDecl(Pattern,
|
||||
/*InstantiatingVarTemplate=*/true));
|
||||
|
||||
DeclContext *DC = Owner;
|
||||
|
||||
|
@ -2649,8 +2651,6 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
|
|||
InstPartialSpec->setInstantiatedFromMember(PartialSpec);
|
||||
InstPartialSpec->setTypeAsWritten(WrittenTy);
|
||||
|
||||
InstPartialSpec->setAccess(PartialSpec->getAccess());
|
||||
|
||||
// Add this partial specialization to the set of variable template partial
|
||||
// specializations. The instantiation of the initializer is not necessary.
|
||||
VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0);
|
||||
|
@ -3314,9 +3314,8 @@ VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl(
|
|||
void Sema::BuildVariableInstantiation(
|
||||
VarDecl *NewVar, VarDecl *OldVar,
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
LateInstantiatedAttrVec *LateAttrs,
|
||||
LocalInstantiationScope *StartingScope,
|
||||
bool ForVarTemplate) {
|
||||
LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *StartingScope,
|
||||
bool InstantiatingVarTemplate) {
|
||||
|
||||
// If we are instantiating a static data member defined
|
||||
// out-of-line, the instantiation will have the same lexical
|
||||
|
@ -3354,15 +3353,14 @@ void Sema::BuildVariableInstantiation(
|
|||
} else if (!isa<VarTemplateSpecializationDecl>(NewVar) &&
|
||||
OldVar->hasLinkage())
|
||||
LookupQualifiedName(Previous, NewVar->getDeclContext(), false);
|
||||
|
||||
CheckVariableDeclaration(NewVar, Previous, ForVarTemplate);
|
||||
CheckVariableDeclaration(NewVar, Previous);
|
||||
|
||||
if (OldVar->isOutOfLine()) {
|
||||
OldVar->getLexicalDeclContext()->addDecl(NewVar);
|
||||
if (!ForVarTemplate)
|
||||
if (!InstantiatingVarTemplate)
|
||||
NewVar->getDeclContext()->makeDeclVisibleInContext(NewVar);
|
||||
} else {
|
||||
if (!ForVarTemplate)
|
||||
if (!InstantiatingVarTemplate)
|
||||
NewVar->getDeclContext()->addDecl(NewVar);
|
||||
if (NewVar->getDeclContext()->isFunctionOrMethod())
|
||||
CurrentInstantiationScope->InstantiatedLocal(OldVar, NewVar);
|
||||
|
@ -3370,13 +3368,13 @@ void Sema::BuildVariableInstantiation(
|
|||
|
||||
// Link instantiations of static data members back to the template from
|
||||
// which they were instantiated.
|
||||
if (NewVar->isStaticDataMember() && !ForVarTemplate)
|
||||
if (NewVar->isStaticDataMember() && !InstantiatingVarTemplate)
|
||||
NewVar->setInstantiationOfStaticDataMember(OldVar,
|
||||
TSK_ImplicitInstantiation);
|
||||
|
||||
if (isa<VarTemplateSpecializationDecl>(NewVar)) {
|
||||
// Do not instantiate the variable just yet.
|
||||
} else if (ForVarTemplate) {
|
||||
} else if (InstantiatingVarTemplate) {
|
||||
assert(!NewVar->getInit() &&
|
||||
"A variable should not have an initializer if it is templated"
|
||||
" and we are instantiating its template");
|
||||
|
|
|
@ -2,61 +2,63 @@
|
|||
// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s
|
||||
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s
|
||||
|
||||
#define CONST const
|
||||
|
||||
class A {
|
||||
template<typename T> const T wrong; // expected-error {{member 'wrong' declared as a template}}
|
||||
template<typename T> const T wrong_init = 5; // expected-error {{member 'wrong_init' declared as a template}}
|
||||
template<typename T, typename T0> static const T right = T(100);
|
||||
template<typename T> static const T right<T,int> = 5;
|
||||
template<typename T> const int right<int,T>; // expected-error {{member 'right' declared as a template}}
|
||||
template<typename T> const float right<float,T> = 5; // expected-error {{member 'right' declared as a template}}
|
||||
template<> static const int right<int,int> = 7; // expected-error {{explicit specialization of 'right' in class scope}}
|
||||
template<> static const float right<float,int>; // expected-error {{explicit specialization of 'right' in class scope}}
|
||||
template static const int right<int,int>; // expected-error {{template specialization requires 'template<>'}} \
|
||||
template<typename T> CONST T wrong; // expected-error {{member 'wrong' declared as a template}}
|
||||
template<typename T> CONST T wrong_init = 5; // expected-error {{member 'wrong_init' declared as a template}}
|
||||
template<typename T, typename T0> static CONST T right = T(100);
|
||||
template<typename T> static CONST T right<T,int> = 5;
|
||||
template<typename T> CONST int right<int,T>; // expected-error {{member 'right' declared as a template}}
|
||||
template<typename T> CONST float right<float,T> = 5; // expected-error {{member 'right' declared as a template}}
|
||||
template<> static CONST int right<int,int> = 7; // expected-error {{explicit specialization of 'right' in class scope}}
|
||||
template<> static CONST float right<float,int>; // expected-error {{explicit specialization of 'right' in class scope}}
|
||||
template static CONST int right<int,int>; // expected-error {{template specialization requires 'template<>'}} \
|
||||
// expected-error {{explicit specialization of 'right' in class scope}}
|
||||
};
|
||||
|
||||
namespace out_of_line {
|
||||
class B0 {
|
||||
template<typename T, typename T0> static const T right = T(100);
|
||||
template<typename T> static const T right<T,int> = T(5);
|
||||
template<typename T, typename T0> static CONST T right = T(100);
|
||||
template<typename T> static CONST T right<T,int> = T(5);
|
||||
};
|
||||
template<> const int B0::right<int,int> = 7;
|
||||
template const int B0::right<int,int>;
|
||||
template<> const int B0::right<int,float>;
|
||||
template const int B0::right<int,float>;
|
||||
template<> CONST int B0::right<int,int> = 7;
|
||||
template CONST int B0::right<int,int>;
|
||||
template<> CONST int B0::right<int,float>;
|
||||
template CONST int B0::right<int,float>;
|
||||
|
||||
class B1 {
|
||||
template<typename T, typename T0> static const T right;
|
||||
template<typename T> static const T right<T,int>;
|
||||
template<typename T, typename T0> static CONST T right;
|
||||
template<typename T> static CONST T right<T,int>;
|
||||
};
|
||||
template<typename T, typename T0> const T B1::right = T(100);
|
||||
template<typename T> const T B1::right<T,int> = T(5);
|
||||
template<typename T, typename T0> CONST T B1::right = T(100);
|
||||
template<typename T> CONST T B1::right<T,int> = T(5);
|
||||
|
||||
class B2 {
|
||||
template<typename T, typename T0> static const T right = T(100); // expected-note {{previous definition is here}}
|
||||
template<typename T> static const T right<T,int> = T(5); // expected-note {{previous definition is here}}
|
||||
template<typename T, typename T0> static CONST T right = T(100); // expected-note {{previous definition is here}}
|
||||
template<typename T> static CONST T right<T,int> = T(5); // expected-note {{previous definition is here}}
|
||||
};
|
||||
template<typename T, typename T0> const T B2::right = T(100); // expected-error {{redefinition of 'right'}}
|
||||
template<typename T> const T B2::right<T,int> = T(5); // expected-error {{redefinition of 'right'}}
|
||||
template<typename T, typename T0> CONST T B2::right = T(100); // expected-error {{redefinition of 'right'}}
|
||||
template<typename T> CONST T B2::right<T,int> = T(5); // expected-error {{redefinition of 'right'}}
|
||||
|
||||
class B3 {
|
||||
template<typename T, typename T0> static const T right = T(100);
|
||||
template<typename T> static const T right<T,int> = T(5);
|
||||
template<typename T, typename T0> static CONST T right = T(100);
|
||||
template<typename T> static CONST T right<T,int> = T(5);
|
||||
};
|
||||
template<typename T, typename T0> const T B3::right; // expected-error {{forward declaration of variable template cannot have a nested name specifier}}
|
||||
template<typename T> const T B3::right<T,int>; // expected-error {{forward declaration of variable template partial specialization cannot have a nested name specifier}}
|
||||
template<typename T, typename T0> CONST T B3::right; // expected-error {{forward declaration of variable template cannot have a nested name specifier}}
|
||||
template<typename T> CONST T B3::right<T,int>; // expected-error {{forward declaration of variable template partial specialization cannot have a nested name specifier}}
|
||||
|
||||
class B4 {
|
||||
template<typename T, typename T0> static const T right;
|
||||
template<typename T> static const T right<T,int>;
|
||||
template<typename T, typename T0> static const T right_def = T(100);
|
||||
template<typename T> static const T right_def<T,int>; // expected-note {{explicit instantiation refers here}}
|
||||
template<typename T, typename T0> static CONST T right;
|
||||
template<typename T> static CONST T right<T,int>;
|
||||
template<typename T, typename T0> static CONST T right_def = T(100);
|
||||
template<typename T> static CONST T right_def<T,int>; // expected-note {{explicit instantiation refers here}}
|
||||
};
|
||||
template<typename T, typename T0> const T B4::right; // expected-error {{forward declaration of variable template cannot have a nested name specifier}}
|
||||
template<typename T> const T B4::right<T,int>; // expected-error {{forward declaration of variable template partial specialization cannot have a nested name specifier}} \
|
||||
template<typename T, typename T0> CONST T B4::right; // expected-error {{forward declaration of variable template cannot have a nested name specifier}}
|
||||
template<typename T> CONST T B4::right<T,int>; // expected-error {{forward declaration of variable template partial specialization cannot have a nested name specifier}} \
|
||||
// expected-note {{explicit instantiation refers here}}
|
||||
template const int B4::right<int,int>; // expected-error {{explicit instantiation of undefined static data member template 'right' of class}}
|
||||
template const int B4::right_def<int,int>; // expected-error {{explicit instantiation of undefined static data member template 'right_def' of class}}
|
||||
template CONST int B4::right<int,int>; // expected-error {{explicit instantiation of undefined static data member template 'right' of class}}
|
||||
template CONST int B4::right_def<int,int>; // expected-error {{explicit instantiation of undefined static data member template 'right_def' of class}}
|
||||
}
|
||||
|
||||
namespace non_const_init {
|
||||
|
@ -80,19 +82,19 @@ namespace non_const_init {
|
|||
template int B::wrong_inst_fixed<int>;
|
||||
|
||||
class C {
|
||||
template<typename T> static const T right_inst = T(10);
|
||||
template<typename T> static const T right_inst<T*> = T(100);
|
||||
template<typename T> static CONST T right_inst = T(10);
|
||||
template<typename T> static CONST T right_inst<T*> = T(100);
|
||||
};
|
||||
template const int C::right_inst<int>;
|
||||
template const int C::right_inst<int*>;
|
||||
template CONST int C::right_inst<int>;
|
||||
template CONST int C::right_inst<int*>;
|
||||
|
||||
namespace pointers {
|
||||
|
||||
struct C0 {
|
||||
template<typename U> static U Data;
|
||||
template<typename U> static const U Data<U*> = U(); // Okay
|
||||
template<typename U> static CONST U Data<U*> = U(); // Okay
|
||||
};
|
||||
template const int C0::Data<int*>;
|
||||
template CONST int C0::Data<int*>;
|
||||
|
||||
struct C1a {
|
||||
template<typename U> static U Data;
|
||||
|
@ -103,10 +105,10 @@ namespace non_const_init {
|
|||
|
||||
struct C1b {
|
||||
template<typename U> static U Data;
|
||||
template<typename U> static const U* Data<U>; // Okay, with out-of-line definition
|
||||
template<typename U> static CONST U* Data<U>; // Okay, with out-of-line definition
|
||||
};
|
||||
template<typename T> const T* C1b::Data<T> = (T*)(0);
|
||||
template const int* C1b::Data<int>;
|
||||
template<typename T> CONST T* C1b::Data<T> = (T*)(0);
|
||||
template CONST int* C1b::Data<int>;
|
||||
|
||||
struct C2a {
|
||||
template<typename U> static U Data;
|
||||
|
@ -116,9 +118,9 @@ namespace non_const_init {
|
|||
|
||||
struct C2b { // FIXME: ?!? Should this be an error? pointer-types are automatically non-const?
|
||||
template<typename U> static U Data;
|
||||
template<typename U> static const U* Data<U> = (U*)(0); // expected-error {{non-const static data member must be initialized out of line}}
|
||||
template<typename U> static CONST U* Data<U> = (U*)(0); // expected-error {{non-const static data member must be initialized out of line}}
|
||||
};
|
||||
template const int* C2b::Data<int>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2b::Data<int>' requested here}}
|
||||
template CONST int* C2b::Data<int>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2b::Data<int>' requested here}}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,9 +133,9 @@ namespace in_class_template {
|
|||
template<typename T>
|
||||
class D0 {
|
||||
template<typename U> static U Data;
|
||||
template<typename U> static const U Data<U*> = U();
|
||||
template<typename U> static CONST U Data<U*> = U();
|
||||
};
|
||||
template const int D0<float>::Data<int*>;
|
||||
template CONST int D0<float>::Data<int*>;
|
||||
|
||||
template<typename T>
|
||||
class D1 {
|
||||
|
@ -152,27 +154,27 @@ namespace in_class_template {
|
|||
template<>
|
||||
template<typename U> U* D2<float>::Data<U*> = (U*)(0) + 1;
|
||||
template int* D1<float>::Data<int*>;
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct D3 {
|
||||
template<typename U> static const U Data = U(100);
|
||||
template<typename U> static CONST U Data = U(100);
|
||||
};
|
||||
template const int D3<float>::Data<int>;
|
||||
template CONST int D3<float>::Data<int>;
|
||||
#ifndef PRECXX11
|
||||
static_assert(D3<float>::Data<int> == 100, "");
|
||||
#endif
|
||||
|
||||
namespace bug_files {
|
||||
// FIXME: A bug has been filed addressing an issue similar to these.
|
||||
// FIXME: A bug has been filed addressing an issue similar to these.
|
||||
// No error diagnosis should be produced, because an
|
||||
// explicit specialization of a member templates of class
|
||||
// template specialization should not inherit the partial
|
||||
// explicit specialization of a member templates of class
|
||||
// template specialization should not inherit the partial
|
||||
// specializations from the class template specialization.
|
||||
|
||||
template<typename T>
|
||||
class D0 {
|
||||
template<typename U> static U Data;
|
||||
template<typename U> static const U Data<U*> = U(10); // expected-note {{previous definition is here}}
|
||||
template<typename U> static CONST U Data<U*> = U(10); // expected-note {{previous definition is here}}
|
||||
};
|
||||
template<>
|
||||
template<typename U> U D0<float>::Data<U*> = U(100); // expected-error{{redefinition of 'Data'}}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// RUN: %clang_cc1 -verify -fsyntax-only -Wno-c++11-extensions -Wno-c++1y-extensions %s
|
||||
// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s -DCXX11
|
||||
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s -DCXX11
|
||||
// RUN: %clang_cc1 -verify -fsyntax-only -Wno-c++11-extensions -Wno-c++1y-extensions %s -DPRECXX11
|
||||
// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s
|
||||
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s
|
||||
|
||||
#ifdef CXX11
|
||||
#define CONST constexpr
|
||||
#else
|
||||
#ifdef PRECXX11
|
||||
#define CONST const
|
||||
#else
|
||||
#define CONST constexpr
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
|
@ -15,7 +15,7 @@ template<typename T>
|
|||
CONST T cpi = T(3.1415926535897932385); // expected-note {{template is declared here}}
|
||||
|
||||
template<typename T> extern CONST T vc;
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
// expected-error@-2 {{constexpr variable declaration must be a definition}}
|
||||
#endif
|
||||
|
||||
|
@ -46,7 +46,7 @@ namespace use_in_top_level_funcs {
|
|||
|
||||
double use_circular_area(double r) {
|
||||
CONST float t = const_circular_area(2.0) - 12;
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
static_assert(const_circular_area(2) == 12, "");
|
||||
CONST int test = (t > 0) && (t < 1);
|
||||
static_assert(test, "");
|
||||
|
@ -104,7 +104,7 @@ namespace odr_tmpl {
|
|||
// expected-note {{previous definition is here}}
|
||||
template<typename T> extern int v; // expected-error {{redefinition of 'v' with a different type: 'int' vs 'T'}}
|
||||
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
template<typename T> extern auto v; // expected-error {{declaration of variable 'v' with type 'auto' requires an initializer}}
|
||||
#endif
|
||||
|
||||
|
@ -112,7 +112,7 @@ namespace odr_tmpl {
|
|||
extern int var; // expected-error {{redefinition of 'var' as different kind of symbol}}
|
||||
}
|
||||
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
namespace pvt_auto {
|
||||
template<typename T> auto v0; // expected-error {{declaration of variable 'v0' with type 'auto' requires an initializer}}
|
||||
template<typename T> auto v1 = T(); // expected-note {{previous definition is here}}
|
||||
|
@ -159,7 +159,7 @@ namespace explicit_instantiation {
|
|||
template CONST int pi1<int>; // expected-note {{previous explicit instantiation is here}}
|
||||
template CONST int pi1<int>; // expected-error {{duplicate explicit instantiation of 'pi1<int>'}}
|
||||
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
namespace auto_var {
|
||||
template<typename T> auto var0 = T();
|
||||
template auto var0<int>; // expected-error {{'auto' variable template instantiation is not allowed}}
|
||||
|
@ -188,7 +188,7 @@ namespace explicit_specialization {
|
|||
|
||||
template<> CONST int pi2<int,int> = 4;
|
||||
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
void foo() {
|
||||
static_assert(pi2<int,int> == 4, "");
|
||||
static_assert(pi2<float,int> == 2, "");
|
||||
|
@ -242,13 +242,13 @@ namespace explicit_specialization {
|
|||
T pi0 = T(3.1415926535897932385);
|
||||
|
||||
template<> int pi0<int> = 10; // expected-note 3{{previous definition is here}}
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
// expected-note@-2 {{previous definition is here}}
|
||||
#endif
|
||||
template<> int pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}}
|
||||
template<> CONST int pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'const int' vs 'int'}}
|
||||
template<> float pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'float' vs 'int'}}
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
template<> auto pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}}
|
||||
#endif
|
||||
|
||||
|
@ -289,7 +289,7 @@ namespace explicit_specialization {
|
|||
template<typename T> CONST int pi2<T,int> = 2;
|
||||
}
|
||||
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
namespace auto_var {
|
||||
template<typename T, typename> auto var0 = T();
|
||||
template<typename T> auto var0<T,int> = T();
|
||||
|
@ -314,7 +314,7 @@ namespace explicit_specialization {
|
|||
// TODO:
|
||||
template<typename T> T var = T();
|
||||
template<typename T> T* var<T> = new T();
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
template<typename T> auto var<T*> = T(); // expected-note {{previous definition is here}}
|
||||
template<typename T> T var<T*> = T(); // expected-error {{redefinition of 'var' with a different type: 'T' vs 'auto'}}
|
||||
#endif
|
||||
|
@ -323,7 +323,7 @@ namespace explicit_specialization {
|
|||
|
||||
namespace narrowing {
|
||||
template<typename T> T v = {1234}; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1234 to}}
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
// expected-error@-2 {{constant expression evaluates to 1234 which cannot be narrowed to type 'char'}}\
|
||||
// expected-note@-2 {{override this message by inserting an explicit cast}}
|
||||
#endif
|
||||
|
@ -338,7 +338,7 @@ namespace attributes {
|
|||
// TODO:
|
||||
}
|
||||
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
namespace arrays {
|
||||
template<typename T>
|
||||
T* arr = new T[10]{T(10), T(23)};
|
||||
|
@ -390,13 +390,13 @@ namespace nested {
|
|||
namespace n1 {
|
||||
template<typename T>
|
||||
T pi1a = T(3.1415926535897932385);
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
// expected-note@-2 {{explicit instantiation refers here}}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
T pi1b = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}}
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
// expected-note@-2 {{explicit instantiation refers here}}
|
||||
#endif
|
||||
}
|
||||
|
@ -406,7 +406,7 @@ namespace nested {
|
|||
int i1 = pi1a<int>;
|
||||
|
||||
template float pi1a<float>;
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
// expected-error@-2 {{explicit instantiation of 'pi1a<float>' not in a namespace enclosing 'n1'}}
|
||||
#endif
|
||||
float f1 = pi1a<float>;
|
||||
|
@ -419,7 +419,7 @@ namespace nested {
|
|||
int i1 = n1::pi1b<int>;
|
||||
|
||||
template float n1::pi1b<float>;
|
||||
#ifdef CXX11
|
||||
#ifndef PRECXX11
|
||||
// expected-error@-2 {{explicit instantiation of 'pi1b<float>' not in a namespace enclosing 'n1'}}
|
||||
#endif
|
||||
float f1 = n1::pi1b<float>;
|
||||
|
|
Loading…
Reference in New Issue