Refactor for clarity and simplicity.

llvm-svn: 188974
This commit is contained in:
Larisse Voufo 2013-08-22 00:59:14 +00:00
parent 6c46216daf
commit 72caf2bb6b
8 changed files with 143 additions and 152 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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.

View File

@ -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;

View File

@ -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());

View File

@ -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");

View File

@ -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'}}

View File

@ -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>;