mirror of https://github.com/microsoft/clang.git
Revert rC330794 and some dependent tiny bug fixes
See Richard's humbling feedback here: http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20180423/226482.html http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20180423/226486.html Wish I'd had the patience to solicit the feedback prior to committing :) Sorry for the noise guys. Thank you Richard for being the steward that clang deserves! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@330888 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c022c7bd37
commit
9626b8d4ee
|
@ -3015,46 +3015,6 @@ public:
|
|||
static bool classofKind(Kind K) { return K == VarTemplate; }
|
||||
};
|
||||
|
||||
/// \brief Represents a C++2a ([temp] p1) concept-definition.
|
||||
class ConceptDecl : public TemplateDecl {
|
||||
protected:
|
||||
Expr *ConstraintExpr;
|
||||
|
||||
ConceptDecl(DeclContext *DC,
|
||||
SourceLocation NameLoc, DeclarationName Name,
|
||||
TemplateParameterList *Params,
|
||||
Expr *ConstraintExpr)
|
||||
: TemplateDecl(nullptr, Concept, DC, NameLoc, Name, Params),
|
||||
ConstraintExpr(ConstraintExpr) {};
|
||||
public:
|
||||
static ConceptDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation NameLoc, DeclarationName Name,
|
||||
TemplateParameterList *Params,
|
||||
Expr *ConstraintExpr);
|
||||
static ConceptDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
|
||||
Expr *getConstraintExpr() const {
|
||||
return ConstraintExpr;
|
||||
}
|
||||
|
||||
void setConstraintExpr(Expr *CE) {
|
||||
ConstraintExpr = CE;
|
||||
}
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY {
|
||||
return SourceRange(getTemplateParameters()->getTemplateLoc(),
|
||||
getConstraintExpr()->getLocEnd());
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == Concept; }
|
||||
|
||||
friend class ASTReader;
|
||||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
};
|
||||
|
||||
inline NamedDecl *getAsNamedDecl(TemplateParameter P) {
|
||||
if (auto *PD = P.dyn_cast<TemplateTypeParmDecl *>())
|
||||
return PD;
|
||||
|
|
|
@ -1722,13 +1722,6 @@ DEF_TRAVERSE_TMPL_DECL(Class)
|
|||
DEF_TRAVERSE_TMPL_DECL(Var)
|
||||
DEF_TRAVERSE_TMPL_DECL(Function)
|
||||
|
||||
DEF_TRAVERSE_DECL(ConceptDecl, {
|
||||
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
|
||||
TRY_TO(TraverseStmt(D->getConstraintExpr()));
|
||||
// FIXME: Traverse all the concept specializations (once we implement forming
|
||||
// template-ids with them).
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
|
||||
// D is the "T" in something like
|
||||
// template <template <typename> class T> class container { };
|
||||
|
|
|
@ -69,7 +69,6 @@ def Named : Decl<"named declarations", 1>;
|
|||
def TypeAliasTemplate : DDecl<RedeclarableTemplate>;
|
||||
def TemplateTemplateParm : DDecl<Template>;
|
||||
def BuiltinTemplate : DDecl<Template>;
|
||||
def Concept : DDecl<Template>;
|
||||
def Using : DDecl<Named>;
|
||||
def UsingPack : DDecl<Named>;
|
||||
def UsingShadow : DDecl<Named>;
|
||||
|
|
|
@ -1150,24 +1150,6 @@ def err_pragma_cannot_end_force_cuda_host_device : Error<
|
|||
"force_cuda_host_device begin">;
|
||||
} // end of Parse Issue category.
|
||||
|
||||
let CategoryName = "Concepts Issue" in {
|
||||
def err_concept_at_non_namespace_scope : Error<
|
||||
"'concept' can only appear in namespace scope">;
|
||||
|
||||
def err_concept_extra_headers : Error<
|
||||
"extraneous template parameter list in concept definition">;
|
||||
def err_concept_unexpected_scope_spec : Error<
|
||||
"invalid nested name specifier; concepts must be defined in their own namespace">;
|
||||
def err_concept_nontemplate : Error<"concept definition must be a template; "
|
||||
"missing template parameter list">;
|
||||
def err_concept_specialized : Error<
|
||||
"'concept' cannot be "
|
||||
"%select{explicitly specialized|partially specialized}0">;
|
||||
def note_concept_specialized : Note<
|
||||
"'concept' cannot be "
|
||||
"%select{explicitly specialized|partially specialized}0">;
|
||||
}
|
||||
|
||||
let CategoryName = "Modules Issue" in {
|
||||
def err_unexpected_module_decl : Error<
|
||||
"module declaration can only appear at the top level">;
|
||||
|
|
|
@ -2387,16 +2387,33 @@ def warn_private_extern : Warning<
|
|||
def note_private_extern : Note<
|
||||
"use __attribute__((visibility(\"hidden\"))) attribute instead">;
|
||||
|
||||
// C++ Concepts
|
||||
// C++ Concepts TS
|
||||
def err_concept_wrong_decl_kind : Error<
|
||||
"'concept' can only appear on the definition of a function template or variable template">;
|
||||
def err_concept_decls_may_only_appear_in_namespace_scope : Error<
|
||||
"concept declarations may only appear in namespace scope">;
|
||||
def err_function_concept_not_defined : Error<
|
||||
"function concept declaration must be a definition">;
|
||||
def err_var_concept_not_initialized : Error<
|
||||
"variable concept declaration must be initialized">;
|
||||
def err_function_concept_exception_spec : Error<
|
||||
"function concept cannot have exception specification">;
|
||||
def err_concept_decl_invalid_specifiers : Error<
|
||||
"%select{variable|function}0 concept cannot be declared "
|
||||
"'%select{thread_local|inline|friend|constexpr}1'">;
|
||||
def err_function_concept_with_params : Error<
|
||||
"function concept cannot have any parameters">;
|
||||
def err_function_concept_bool_ret : Error<
|
||||
"declared return type of function concept must be 'bool'">;
|
||||
def err_variable_concept_bool_decl : Error<
|
||||
"declared type of variable concept must be 'bool'">;
|
||||
def err_concept_specified_specialization : Error<
|
||||
"'concept' cannot be applied on an "
|
||||
"%select{explicit instantiation|explicit specialization|partial specialization}0">;
|
||||
def err_concept_specialized : Error<
|
||||
"%select{function|variable}0 concept cannot be "
|
||||
"%select{explicitly instantiated|explicitly specialized|partially specialized}1">;
|
||||
|
||||
|
||||
|
||||
def err_concept_initialized_with_non_bool_type : Error<
|
||||
"type of constraint expression must be 'bool' - not '%0'">;
|
||||
def err_concept_no_associated_constraints : Error<
|
||||
"concept may not have associated constraints">;
|
||||
def err_concept_feature_unimplemented : Error<
|
||||
"unimplemented concept feature: %0 (coming soon)">;
|
||||
def err_template_different_associated_constraints : Error<
|
||||
"associated constraints differ in template redeclaration">;
|
||||
|
||||
|
|
|
@ -43,10 +43,10 @@ enum TemplateNameKind {
|
|||
/// whether the template name is assumed to refer to a type template or a
|
||||
/// function template depends on the context in which the template
|
||||
/// name occurs.
|
||||
TNK_Dependent_template_name,
|
||||
/// The name refers to a concept definition.
|
||||
TNK_Concept_template
|
||||
TNK_Dependent_template_name
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -1959,16 +1959,7 @@ private:
|
|||
ParsedAttributesWithRange &Attrs);
|
||||
DeclSpecContext
|
||||
getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context);
|
||||
|
||||
/// \brief Parses declaration-specifiers upto a declarator or ';' emitting
|
||||
/// diagnostics as necessary and storing parsed information within DS.
|
||||
///
|
||||
/// Note: Asides from parsing the routine C/C++ decl-specifiers (which could
|
||||
/// include entire class or enum definitions), this also parses a concept
|
||||
/// definition and stores the appropriate AST representations (for
|
||||
/// class/enum/concept declarations/definitions, decltype
|
||||
/// expression-operands or types, where appropriate) within DS.
|
||||
void ParseDeclarationSpecifiersOrConceptDefinition(
|
||||
void ParseDeclarationSpecifiers(
|
||||
DeclSpec &DS,
|
||||
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
|
||||
AccessSpecifier AS = AS_none,
|
||||
|
@ -2820,11 +2811,6 @@ private:
|
|||
SourceLocation &DeclEnd,
|
||||
AccessSpecifier AS = AS_none);
|
||||
|
||||
/// \brief Parse a single template declaration that declares a concept [c++2a]
|
||||
/// and store the AST node within DS.
|
||||
void ParseConceptDefinition(SourceLocation ConceptLoc, DeclSpec &DS,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
AccessSpecifier AS, DeclSpecContext DSC);
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Modules
|
||||
DeclGroupPtrTy ParseModuleDecl();
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
namespace clang {
|
||||
class ASTContext;
|
||||
class CXXRecordDecl;
|
||||
class ConceptDecl;
|
||||
class TypeLoc;
|
||||
class LangOptions;
|
||||
class IdentifierInfo;
|
||||
|
@ -222,13 +221,10 @@ public:
|
|||
unsigned location_size() const { return Builder.getBuffer().second; }
|
||||
};
|
||||
|
||||
/// \brief Captures information about "decl-specifiers" and also concept
|
||||
/// definitions.
|
||||
/// \brief Captures information about "declaration specifiers".
|
||||
///
|
||||
/// "Declaration specifiers" encompasses storage-class-specifiers,
|
||||
/// type-specifiers, type-qualifiers, and function-specifiers. This includes
|
||||
/// class and enum definitions whose AST representations must be stored - same
|
||||
/// with the expression-operands of decltype.
|
||||
/// type-specifiers, type-qualifiers, and function-specifiers.
|
||||
class DeclSpec {
|
||||
public:
|
||||
/// \brief storage-class-specifier
|
||||
|
@ -367,14 +363,8 @@ private:
|
|||
unsigned Constexpr_specified : 1;
|
||||
|
||||
union {
|
||||
// Valid if isTypeRep is true.
|
||||
UnionParsedType TypeRep;
|
||||
// If we parsed a concept, class, enum (etc.) defintion or elaborated type
|
||||
// specifier, this stores the AST representation. This is valid if either
|
||||
// isDeclRep or isConceptSpecified returns true.
|
||||
Decl *DeclRep;
|
||||
// If we parsed a typeof(e) or decltype(e) operator, this stores the
|
||||
// expression 'e'. Valid if isExprRep is true.
|
||||
Expr *ExprRep;
|
||||
};
|
||||
|
||||
|
@ -403,11 +393,6 @@ private:
|
|||
SourceLocation FS_forceinlineLoc;
|
||||
SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc;
|
||||
SourceLocation TQ_pipeLoc;
|
||||
|
||||
// Even though 'concept' is not a specifier, we handle it here. This allows us
|
||||
// to reuse infrastructure for diagnosing attributes and invalid
|
||||
// decl-specifiers.
|
||||
SourceLocation ConceptLoc;
|
||||
|
||||
WrittenBuiltinSpecs writtenBS;
|
||||
void SaveWrittenBuiltinSpecs();
|
||||
|
@ -497,10 +482,7 @@ public:
|
|||
bool isTypeSpecOwned() const { return TypeSpecOwned; }
|
||||
bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); }
|
||||
bool isTypeSpecPipe() const { return TypeSpecPipe; }
|
||||
bool isDeclRep() const {
|
||||
return isDeclRep((TST)TypeSpecType);
|
||||
}
|
||||
|
||||
|
||||
ParsedType getRepAsType() const {
|
||||
assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
|
||||
return TypeRep;
|
||||
|
@ -509,19 +491,6 @@ public:
|
|||
assert(isDeclRep((TST) TypeSpecType) && "DeclSpec does not store a decl");
|
||||
return DeclRep;
|
||||
}
|
||||
// This is a template that should only be instantiated with the type
|
||||
// ConceptDecl. By making it a template we only require ConceptDecl to be a
|
||||
// complete type where this function is called.
|
||||
template<class ConceptDeclTy = ConceptDecl>
|
||||
ConceptDeclTy *getRepAsConcept() const {
|
||||
static_assert(std::is_same<ConceptDeclTy, ConceptDecl>::value,
|
||||
"Must only be instantiated with ConceptDecl");
|
||||
assert(isConceptSpecified() && "DeclSpec does not store a concept");
|
||||
|
||||
return cast_or_null<ConceptDeclTy>(DeclRep);
|
||||
}
|
||||
|
||||
|
||||
Expr *getRepAsExpr() const {
|
||||
assert(isExprRep((TST) TypeSpecType) && "DeclSpec does not store an expr");
|
||||
return ExprRep;
|
||||
|
@ -696,20 +665,6 @@ public:
|
|||
assert(isDeclRep((TST) TypeSpecType));
|
||||
DeclRep = Rep;
|
||||
}
|
||||
// This function can only be instantiated with ConceptDecl. We made it a
|
||||
// template so that ConceptDecl only has to be defined where this is called.
|
||||
template <class ConceptDeclTy = ConceptDecl>
|
||||
void
|
||||
setConceptRep(typename llvm::identity<ConceptDeclTy>::argument_type *Rep) {
|
||||
static_assert(std::is_same<ConceptDeclTy, ConceptDecl>::value,
|
||||
"Must only be instantiated with ConceptDecl");
|
||||
assert(isConceptSpecified() && "DeclSpec does not store a concept");
|
||||
assert(!DeclRep &&
|
||||
"why is this not null? We expect this function to be called only "
|
||||
"once, and usually right after DeclRep was set to null");
|
||||
DeclRep = Rep;
|
||||
}
|
||||
|
||||
void UpdateTypeRep(ParsedType Rep) {
|
||||
assert(isTypeRep((TST) TypeSpecType));
|
||||
TypeRep = Rep;
|
||||
|
@ -739,8 +694,6 @@ public:
|
|||
unsigned &DiagID);
|
||||
bool SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
|
||||
unsigned &DiagID);
|
||||
bool setConceptSpec(SourceLocation Loc, const char *&PrevSpec,
|
||||
unsigned &DiagID, const PrintingPolicy &P);
|
||||
|
||||
bool isFriendSpecified() const { return Friend_specified; }
|
||||
SourceLocation getFriendSpecLoc() const { return FriendLoc; }
|
||||
|
@ -751,8 +704,6 @@ public:
|
|||
bool isConstexprSpecified() const { return Constexpr_specified; }
|
||||
SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; }
|
||||
|
||||
bool isConceptSpecified() const { return ConceptLoc.isValid(); }
|
||||
SourceLocation getConceptLoc() const { return ConceptLoc; }
|
||||
void ClearConstexprSpec() {
|
||||
Constexpr_specified = false;
|
||||
ConstexprLoc = SourceLocation();
|
||||
|
|
|
@ -2126,7 +2126,6 @@ public:
|
|||
|
||||
Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
|
||||
RecordDecl *&AnonRecord);
|
||||
|
||||
Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
|
||||
MultiTemplateParamsArg TemplateParams,
|
||||
bool IsExplicitInstantiation,
|
||||
|
@ -6230,13 +6229,6 @@ public:
|
|||
SourceLocation TemplateLoc,
|
||||
const TemplateArgumentListInfo *TemplateArgs);
|
||||
|
||||
ExprResult
|
||||
CheckConceptTemplateId(const CXXScopeSpec &SS,
|
||||
const DeclarationNameInfo &NameInfo,
|
||||
ConceptDecl *Template,
|
||||
SourceLocation TemplateLoc,
|
||||
const TemplateArgumentListInfo *TemplateArgs);
|
||||
|
||||
ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
|
||||
SourceLocation TemplateKWLoc,
|
||||
LookupResult &R,
|
||||
|
@ -6515,13 +6507,6 @@ public:
|
|||
const TemplateArgument *Args,
|
||||
unsigned NumArgs);
|
||||
|
||||
// Concepts
|
||||
ConceptDecl *ActOnConceptDefinition(
|
||||
Scope *S,
|
||||
MultiTemplateParamsArg TemplateParameterLists,
|
||||
IdentifierInfo *Name, SourceLocation NameLoc,
|
||||
Expr *ConstraintExpr);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ Variadic Templates (C++0x [temp.variadic])
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
|
|
@ -1408,9 +1408,6 @@ namespace serialization {
|
|||
/// \brief A TypeAliasTemplateDecl record.
|
||||
DECL_TYPE_ALIAS_TEMPLATE,
|
||||
|
||||
/// \brief A ConceptDecl record.
|
||||
DECL_CONCEPT,
|
||||
|
||||
/// \brief A StaticAssertDecl record.
|
||||
DECL_STATIC_ASSERT,
|
||||
|
||||
|
|
|
@ -466,7 +466,6 @@ namespace {
|
|||
bool DumpRefOnly);
|
||||
template<typename TemplateDecl>
|
||||
void VisitTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst);
|
||||
void VisitConceptDecl(const ConceptDecl *D);
|
||||
void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
|
||||
void VisitClassTemplateDecl(const ClassTemplateDecl *D);
|
||||
void VisitClassTemplateSpecializationDecl(
|
||||
|
@ -1578,12 +1577,6 @@ void ASTDumper::VisitTemplateDecl(const TemplateDecl *D,
|
|||
!D->isCanonicalDecl());
|
||||
}
|
||||
|
||||
void ASTDumper::VisitConceptDecl(const ConceptDecl *D) {
|
||||
dumpName(D);
|
||||
dumpTemplateParameters(D->getTemplateParameters());
|
||||
dumpStmt(D->getConstraintExpr());
|
||||
}
|
||||
|
||||
void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
|
||||
// FIXME: We don't add a declaration of a function template specialization
|
||||
// to its context when it's explicitly instantiated, so dump explicit
|
||||
|
|
|
@ -724,7 +724,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
|||
case Binding:
|
||||
case NonTypeTemplateParm:
|
||||
case VarTemplate:
|
||||
case Concept:
|
||||
// These (C++-only) declarations are found by redeclaration lookup for
|
||||
// tag types, so we include them in the tag namespace.
|
||||
return IDNS_Ordinary | IDNS_Tag;
|
||||
|
|
|
@ -788,27 +788,6 @@ ClassTemplateSpecializationDecl::getSourceRange() const {
|
|||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ConceptDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
ConceptDecl *ConceptDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation NameLoc, DeclarationName Name,
|
||||
TemplateParameterList *Params,
|
||||
Expr *ConstraintExpr) {
|
||||
// TODO: Do we need this?
|
||||
// AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
|
||||
return new (C, DC) ConceptDecl(DC, NameLoc, Name, Params, ConstraintExpr);
|
||||
}
|
||||
|
||||
ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C,
|
||||
unsigned ID) {
|
||||
ConceptDecl *Result = new (C, ID) ConceptDecl(nullptr, SourceLocation(),
|
||||
DeclarationName(),
|
||||
nullptr, nullptr);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ClassTemplatePartialSpecializationDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -105,7 +105,6 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
|
|||
case Decl::OMPThreadPrivate:
|
||||
case Decl::OMPCapturedExpr:
|
||||
case Decl::Empty:
|
||||
case Decl::Concept:
|
||||
// None of these decls require codegen support.
|
||||
return;
|
||||
|
||||
|
|
|
@ -4423,7 +4423,6 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
|
|||
case Decl::TypeAliasTemplate:
|
||||
case Decl::Block:
|
||||
case Decl::Empty:
|
||||
case Decl::Concept:
|
||||
break;
|
||||
case Decl::Using: // using X; [C++]
|
||||
if (CGDebugInfo *DI = getModuleDebugInfo())
|
||||
|
|
|
@ -1739,8 +1739,7 @@ Parser::ParseSimpleDeclaration(DeclaratorContext Context,
|
|||
ParsingDeclSpec DS(*this);
|
||||
|
||||
DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext(Context);
|
||||
ParseDeclarationSpecifiersOrConceptDefinition(DS, ParsedTemplateInfo(),
|
||||
AS_none, DSContext);
|
||||
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, DSContext);
|
||||
|
||||
// If we had a free-standing type definition with a missing semicolon, we
|
||||
// may get this far before the problem becomes obvious.
|
||||
|
@ -2387,8 +2386,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
|
|||
/// specifier-qualifier-list is a subset of declaration-specifiers. Just
|
||||
/// parse declaration-specifiers and complain about extra stuff.
|
||||
/// TODO: diagnose attribute-specifiers and alignment-specifiers.
|
||||
ParseDeclarationSpecifiersOrConceptDefinition(DS, ParsedTemplateInfo(), AS,
|
||||
DSC);
|
||||
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC);
|
||||
|
||||
// Validate declspec for type-name.
|
||||
unsigned Specs = DS.getParsedSpecifiers();
|
||||
|
@ -2873,12 +2871,11 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
|
|||
// and call ParsedFreeStandingDeclSpec as appropriate.
|
||||
DS.ClearTypeSpecType();
|
||||
ParsedTemplateInfo NotATemplate;
|
||||
ParseDeclarationSpecifiersOrConceptDefinition(DS, NotATemplate, AS, DSContext,
|
||||
LateAttrs);
|
||||
ParseDeclarationSpecifiers(DS, NotATemplate, AS, DSContext, LateAttrs);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseDeclarationSpecifiersOrConceptDefinition
|
||||
/// ParseDeclarationSpecifiers
|
||||
/// declaration-specifiers: [C99 6.7]
|
||||
/// storage-class-specifier declaration-specifiers[opt]
|
||||
/// type-specifier declaration-specifiers[opt]
|
||||
|
@ -2905,8 +2902,7 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
|
|||
/// [OpenCL] '__kernel'
|
||||
/// 'friend': [C++ dcl.friend]
|
||||
/// 'constexpr': [C++0x dcl.constexpr]
|
||||
/// [C++2a] 'concept'
|
||||
void Parser::ParseDeclarationSpecifiersOrConceptDefinition(DeclSpec &DS,
|
||||
void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
AccessSpecifier AS,
|
||||
DeclSpecContext DSContext,
|
||||
|
@ -3684,11 +3680,7 @@ void Parser::ParseDeclarationSpecifiersOrConceptDefinition(DeclSpec &DS,
|
|||
ConsumeToken();
|
||||
ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSContext);
|
||||
continue;
|
||||
|
||||
case tok::kw_concept:
|
||||
ConsumeToken();
|
||||
ParseConceptDefinition(Loc, DS, TemplateInfo, AS, DSContext);
|
||||
continue;
|
||||
|
||||
// cv-qualifier:
|
||||
case tok::kw_const:
|
||||
isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID,
|
||||
|
@ -6374,7 +6366,7 @@ void Parser::ParseParameterDeclarationClause(
|
|||
// too much hassle.
|
||||
DS.takeAttributesFrom(FirstArgAttrs);
|
||||
|
||||
ParseDeclarationSpecifiersOrConceptDefinition(DS);
|
||||
ParseDeclarationSpecifiers(DS);
|
||||
|
||||
|
||||
// Parse the declarator. This is "PrototypeContext" or
|
||||
|
|
|
@ -2561,8 +2561,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
|||
if (MalformedTypeSpec)
|
||||
DS.SetTypeSpecError();
|
||||
|
||||
ParseDeclarationSpecifiersOrConceptDefinition(
|
||||
DS, TemplateInfo, AS, DeclSpecContext::DSC_class, &CommonLateParsedAttrs);
|
||||
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DeclSpecContext::DSC_class,
|
||||
&CommonLateParsedAttrs);
|
||||
|
||||
// Turn off colon protection that was set for declspec.
|
||||
X.restore();
|
||||
|
|
|
@ -1490,7 +1490,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
|
|||
cStyleParamWarned = true;
|
||||
}
|
||||
DeclSpec DS(AttrFactory);
|
||||
ParseDeclarationSpecifiersOrConceptDefinition(DS);
|
||||
ParseDeclarationSpecifiers(DS);
|
||||
// Parse the declarator.
|
||||
Declarator ParmDecl(DS, DeclaratorContext::PrototypeContext);
|
||||
ParseDeclarator(ParmDecl);
|
||||
|
@ -2541,7 +2541,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
|
|||
Scope::AtCatchScope);
|
||||
if (Tok.isNot(tok::ellipsis)) {
|
||||
DeclSpec DS(AttrFactory);
|
||||
ParseDeclarationSpecifiersOrConceptDefinition(DS);
|
||||
ParseDeclarationSpecifiers(DS);
|
||||
Declarator ParmDecl(DS, DeclaratorContext::ObjCCatchContext);
|
||||
ParseDeclarator(ParmDecl);
|
||||
|
||||
|
|
|
@ -54,15 +54,6 @@ Parser::ParseDeclarationStartingWithTemplate(DeclaratorContext Context,
|
|||
/// template-declaration: [C++ temp]
|
||||
/// 'export'[opt] 'template' '<' template-parameter-list '>' declaration
|
||||
///
|
||||
/// template-declaration: [C++2a]
|
||||
/// template-head declaration
|
||||
/// template-head concept-definition
|
||||
///
|
||||
/// TODO: requires-clause
|
||||
/// template-head: [C++2a]
|
||||
/// 'export'[opt] 'template' '<' template-parameter-list '>'
|
||||
/// requires-clause[opt]
|
||||
///
|
||||
/// explicit-specialization: [ C++ temp.expl.spec]
|
||||
/// 'template' '<' '>' declaration
|
||||
Decl *
|
||||
|
@ -157,10 +148,13 @@ Parser::ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context,
|
|||
unsigned NewFlags = getCurScope()->getFlags() & ~Scope::TemplateParamScope;
|
||||
ParseScopeFlags TemplateScopeFlags(this, NewFlags, isSpecialization);
|
||||
|
||||
return ParseSingleDeclarationAfterTemplate(
|
||||
Context,
|
||||
ParsedTemplateInfo(&ParamLists, isSpecialization, LastParamListWasEmpty),
|
||||
ParsingTemplateParams, DeclEnd, AS, AccessAttrs);
|
||||
// Parse the actual template declaration.
|
||||
return ParseSingleDeclarationAfterTemplate(Context,
|
||||
ParsedTemplateInfo(&ParamLists,
|
||||
isSpecialization,
|
||||
LastParamListWasEmpty),
|
||||
ParsingTemplateParams,
|
||||
DeclEnd, AS, AccessAttrs);
|
||||
}
|
||||
|
||||
/// \brief Parse a single declaration that declares a template,
|
||||
|
@ -214,7 +208,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
|
|||
// the template parameters.
|
||||
ParsingDeclSpec DS(*this, &DiagsFromTParams);
|
||||
|
||||
ParseDeclarationSpecifiersOrConceptDefinition(DS, TemplateInfo, AS,
|
||||
ParseDeclarationSpecifiers(DS, TemplateInfo, AS,
|
||||
getDeclSpecContextFromDeclaratorContext(Context));
|
||||
|
||||
if (Tok.is(tok::semi)) {
|
||||
|
@ -328,150 +322,6 @@ Parser::ParseSingleDeclarationAfterTemplate(
|
|||
return ThisDecl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Parser::ParseConceptDefinition(SourceLocation ConceptLoc,
|
||||
DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo,
|
||||
AccessSpecifier AS,
|
||||
DeclSpecContext DSC) {
|
||||
|
||||
|
||||
auto DiagnoseAttributes = [this] {
|
||||
ParsedAttributesWithRange attrs(this->AttrFactory);
|
||||
this->MaybeParseGNUAttributes(attrs);
|
||||
this->MaybeParseCXX11Attributes(attrs);
|
||||
this->MaybeParseMicrosoftDeclSpecs(attrs);
|
||||
this->ProhibitAttributes(attrs);
|
||||
};
|
||||
|
||||
|
||||
// If attributes exist after 'concept' kw but before the concept name,
|
||||
// prohibit them for now (if CWG approves attributes on concepts, this is
|
||||
// likely where they will go...).
|
||||
DiagnoseAttributes();
|
||||
|
||||
// Set the concept specifier at ConceptLoc within 'DS' along with emitting any
|
||||
// incompatible decl-specifier diagnostics.
|
||||
{
|
||||
const char *PrevSpec = 0;
|
||||
unsigned int DiagId = 0;
|
||||
if (DS.setConceptSpec(ConceptLoc, PrevSpec, DiagId,
|
||||
Actions.getASTContext().getPrintingPolicy())) {
|
||||
Diag(ConceptLoc, DiagId) << PrevSpec;
|
||||
}
|
||||
Actions.DiagnoseFunctionSpecifiers(DS);
|
||||
}
|
||||
|
||||
if (DSC != DeclSpecContext::DSC_top_level) {
|
||||
Diag(ConceptLoc, diag::err_concept_at_non_namespace_scope);
|
||||
// If we are not in a template parameter context, skip to a '}' or ';'. The
|
||||
// error messages are better if we just ignore this within template
|
||||
// parameter lists.
|
||||
if (DSC != DeclSpecContext::DSC_template_param) {
|
||||
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
|
||||
} else {
|
||||
tok::TokenKind Tokens[] = { tok::comma, tok::greater };
|
||||
SkipUntil(llvm::makeArrayRef(Tokens),
|
||||
StopAtSemi | StopBeforeMatch);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// A scope-guard that (if an error occurs while parsing a concept) skips to
|
||||
// the next semi or closing brace.
|
||||
class SkipUntilSemiOrClosingBraceOnScopeExit {
|
||||
Parser &P;
|
||||
bool Disabled = false;
|
||||
|
||||
public:
|
||||
SkipUntilSemiOrClosingBraceOnScopeExit(Parser &P)
|
||||
: P(P) {}
|
||||
void disable() { Disabled = true; }
|
||||
~SkipUntilSemiOrClosingBraceOnScopeExit() {
|
||||
if (!Disabled) {
|
||||
// Skip until the semi-colon or a '}'.
|
||||
P.SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
|
||||
}
|
||||
}
|
||||
} SkipUntilSemiOrClosingBraceOnScopeExit(*this);
|
||||
|
||||
if (TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate) {
|
||||
Diag(ConceptLoc, diag::err_concept_nontemplate);
|
||||
return;
|
||||
}
|
||||
|
||||
const TemplateParameterLists &ParamLists = *TemplateInfo.TemplateParams;
|
||||
|
||||
|
||||
// More than one TPL wouldn't make sense here.
|
||||
if (ParamLists.size() != 1) {
|
||||
Diag(Tok.getLocation(), diag::err_concept_extra_headers);
|
||||
return;
|
||||
}
|
||||
const TemplateParameterList *const TPL = ParamLists[0];
|
||||
|
||||
// Explicit specializations of concepts are not allowed.
|
||||
if (TPL->getLAngleLoc().getLocWithOffset(1) == TPL->getRAngleLoc()) {
|
||||
assert(!TPL->size() &&
|
||||
"can not have template parameters within empty angle brackets!");
|
||||
Diag(ConceptLoc, diag::err_concept_specialized) << 0;
|
||||
return;
|
||||
}
|
||||
// Concepts can not be defined with nested name specifiers.
|
||||
CXXScopeSpec SS;
|
||||
if (ParseOptionalCXXScopeSpecifier(SS, nullptr,
|
||||
/*EnteringContext=*/false) ||
|
||||
SS.isNotEmpty()) {
|
||||
|
||||
if (SS.isNotEmpty())
|
||||
Diag(Tok.getLocation(), diag::err_concept_unexpected_scope_spec);
|
||||
return;
|
||||
}
|
||||
// An identifier (i.e. the concept-name) should follow 'concept'.
|
||||
if (!Tok.is(tok::identifier)) {
|
||||
Diag(Tok.getLocation(), diag::err_expected) << "concept name";
|
||||
return;
|
||||
}
|
||||
|
||||
IdentifierInfo *Id = Tok.getIdentifierInfo();
|
||||
SourceLocation IdLoc = ConsumeToken();
|
||||
|
||||
// If attributes exist after the identifier, parse them and diagnose
|
||||
DiagnoseAttributes();
|
||||
|
||||
if (!TryConsumeToken(tok::equal)) {
|
||||
Diag(Tok.getLocation(), diag::err_expected) << "equal";
|
||||
return;
|
||||
}
|
||||
|
||||
ExprResult ConstraintExprResult = ParseConstraintExpression();
|
||||
if (ConstraintExprResult.isInvalid()) {
|
||||
Diag(Tok.getLocation(), diag::err_expected_expression)
|
||||
<< "constraint-expression";
|
||||
return;
|
||||
}
|
||||
|
||||
// We can try to create a valid concept decl node now, so disable the
|
||||
// scope-guard.
|
||||
SkipUntilSemiOrClosingBraceOnScopeExit.disable();
|
||||
|
||||
Expr *ConstraintExpr = ConstraintExprResult.get();
|
||||
ConceptDecl *const ConDecl = Actions.ActOnConceptDefinition(
|
||||
getCurScope(), *TemplateInfo.TemplateParams, Id, IdLoc, ConstraintExpr);
|
||||
DS.setConceptRep(ConDecl);
|
||||
|
||||
if (Tok.isNot(tok::semi)) {
|
||||
|
||||
ExpectAndConsume(tok::semi, diag::err_expected_after, "concept");
|
||||
// Push this token back into the preprocessor and change our current token
|
||||
// to ';' so that the rest of the code recovers as though there were an
|
||||
// ';' after the definition.
|
||||
PP.EnterToken(Tok);
|
||||
Tok.setKind(tok::semi);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
|
||||
/// angle brackets. Depth is the depth of this template-parameter-list, which
|
||||
/// is the number of template headers directly enclosing this template header.
|
||||
|
@ -840,8 +690,8 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
|
|||
// FIXME: The type should probably be restricted in some way... Not all
|
||||
// declarators (parts of declarators?) are accepted for parameters.
|
||||
DeclSpec DS(AttrFactory);
|
||||
ParseDeclarationSpecifiersOrConceptDefinition(
|
||||
DS, ParsedTemplateInfo(), AS_none, DeclSpecContext::DSC_template_param);
|
||||
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
|
||||
DeclSpecContext::DSC_template_param);
|
||||
|
||||
// Parse this as a typename.
|
||||
Declarator ParamDecl(DS, DeclaratorContext::TemplateParamContext);
|
||||
|
|
|
@ -1351,7 +1351,6 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
|
|||
case tok::kw_struct:
|
||||
case tok::kw_union:
|
||||
case tok::kw___interface:
|
||||
case tok::kw_concept:
|
||||
// enum-specifier
|
||||
case tok::kw_enum:
|
||||
// cv-qualifier
|
||||
|
|
|
@ -919,7 +919,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
|
|||
AccessSpecifier AS) {
|
||||
MaybeParseMicrosoftAttributes(DS.getAttributes());
|
||||
// Parse the common declaration-specifiers piece.
|
||||
ParseDeclarationSpecifiersOrConceptDefinition(DS, ParsedTemplateInfo(), AS,
|
||||
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS,
|
||||
DeclSpecContext::DSC_top_level);
|
||||
|
||||
// If we had a free-standing type definition with a missing semicolon, we
|
||||
|
@ -1287,7 +1287,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
|
|||
|
||||
// Parse the common declaration-specifiers piece.
|
||||
DeclSpec DS(AttrFactory);
|
||||
ParseDeclarationSpecifiersOrConceptDefinition(DS);
|
||||
ParseDeclarationSpecifiers(DS);
|
||||
|
||||
// C99 6.9.1p6: 'each declaration in the declaration list shall have at
|
||||
// least one declarator'.
|
||||
|
@ -1647,7 +1647,7 @@ bool Parser::TryKeywordIdentFallback(bool DisableKeyword) {
|
|||
/// Actions.getTypeName will not be needed to be called again (e.g. getTypeName
|
||||
/// will not be called twice, once to check whether we have a declaration
|
||||
/// specifier, and another one to get the actual type inside
|
||||
/// ParseDeclarationSpecifiersOrConceptDefinition).
|
||||
/// ParseDeclarationSpecifiers).
|
||||
///
|
||||
/// This returns true if an error occurred.
|
||||
///
|
||||
|
|
|
@ -426,7 +426,6 @@ unsigned DeclSpec::getParsedSpecifiers() const {
|
|||
return Res;
|
||||
}
|
||||
|
||||
|
||||
template <class T> static bool BadSpecifier(T TNew, T TPrev,
|
||||
const char *&PrevSpec,
|
||||
unsigned &DiagID,
|
||||
|
@ -492,6 +491,7 @@ const char *DeclSpec::getSpecifierName(TSS S) {
|
|||
}
|
||||
llvm_unreachable("Unknown typespec!");
|
||||
}
|
||||
|
||||
const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
|
||||
const PrintingPolicy &Policy) {
|
||||
switch (T) {
|
||||
|
@ -969,69 +969,6 @@ bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DeclSpec::setConceptSpec(const SourceLocation Loc, const char *&PrevSpec,
|
||||
unsigned &DiagID, const PrintingPolicy &PP) {
|
||||
assert(Loc.isValid() && "Loc must be valid, since it is used to identify "
|
||||
"that this function was called before");
|
||||
assert(!ConceptLoc.isValid() &&
|
||||
"how is this called if concept was already encountered and triggered "
|
||||
"ParseConceptDefinition which parses upto the semi-colon");
|
||||
|
||||
PrevSpec = nullptr;
|
||||
if (TypeSpecType != TST_unspecified) {
|
||||
PrevSpec = DeclSpec::getSpecifierName(static_cast<TST>(TypeSpecType), PP);
|
||||
ClearTypeSpecType();
|
||||
}
|
||||
if (TypeSpecSign != TSS_unspecified) {
|
||||
PrevSpec = DeclSpec::getSpecifierName(static_cast<TSS>(TypeSpecSign));
|
||||
TypeSpecSign = TSS_unspecified;
|
||||
}
|
||||
if (TypeSpecWidth != TSW_unspecified) {
|
||||
PrevSpec = DeclSpec::getSpecifierName(static_cast<TSW>(TypeSpecWidth));
|
||||
TypeSpecWidth = TSW_unspecified;
|
||||
}
|
||||
if (StorageClassSpec != SCS_unspecified) {
|
||||
PrevSpec = DeclSpec::getSpecifierName(static_cast<SCS>(StorageClassSpec));
|
||||
ClearStorageClassSpecs();
|
||||
}
|
||||
if (ThreadStorageClassSpec != TSCS_unspecified) {
|
||||
PrevSpec =
|
||||
DeclSpec::getSpecifierName(static_cast<TSCS>(ThreadStorageClassSpec));
|
||||
ClearStorageClassSpecs();
|
||||
}
|
||||
if (TypeSpecComplex != TSC_unspecified) {
|
||||
PrevSpec = DeclSpec::getSpecifierName(static_cast<TSC>(TypeSpecComplex));
|
||||
TypeSpecComplex = TSC_unspecified;
|
||||
}
|
||||
if (getTypeQualifiers()) {
|
||||
PrevSpec = DeclSpec::getSpecifierName(static_cast<TQ>(TypeQualifiers));
|
||||
ClearTypeQualifiers();
|
||||
}
|
||||
if (isFriendSpecified()) {
|
||||
PrevSpec = "friend";
|
||||
Friend_specified = false;
|
||||
FriendLoc = SourceLocation();
|
||||
}
|
||||
if (isConstexprSpecified()) {
|
||||
PrevSpec = "constexpr";
|
||||
Constexpr_specified = false;
|
||||
ConstexprLoc = SourceLocation();
|
||||
}
|
||||
if (isInlineSpecified()) {
|
||||
PrevSpec = "inline";
|
||||
FS_inlineLoc = SourceLocation();
|
||||
FS_inline_specified = false;
|
||||
}
|
||||
|
||||
if (PrevSpec) {
|
||||
DiagID = diag::err_invalid_decl_spec_combination;
|
||||
}
|
||||
// We set the concept location regardless of whether an error occurred.
|
||||
DeclRep = nullptr;
|
||||
ConceptLoc = Loc;
|
||||
return PrevSpec; // If this is non-null, an error occurred.
|
||||
}
|
||||
|
||||
void DeclSpec::SaveWrittenBuiltinSpecs() {
|
||||
writtenBS.Sign = getTypeSpecSign();
|
||||
writtenBS.Width = getTypeSpecWidth();
|
||||
|
@ -1333,7 +1270,6 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
|
|||
// TODO: return "auto function" and other bad things based on the real type.
|
||||
|
||||
// 'data definition has no type or storage class'?
|
||||
|
||||
}
|
||||
|
||||
bool DeclSpec::isMissingDeclaratorOk() {
|
||||
|
|
|
@ -4212,12 +4212,6 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
|
|||
MultiTemplateParamsArg TemplateParams,
|
||||
bool IsExplicitInstantiation,
|
||||
RecordDecl *&AnonRecord) {
|
||||
|
||||
// We don't need to do any additional declspecifier checking on concept
|
||||
// definitions since that should already have been done when the concept kw
|
||||
// location was set within DS.
|
||||
if (DS.isConceptSpecified()) return DS.getRepAsConcept();
|
||||
|
||||
Decl *TagD = nullptr;
|
||||
TagDecl *Tag = nullptr;
|
||||
if (DS.getTypeSpecType() == DeclSpec::TST_class ||
|
||||
|
|
|
@ -9467,7 +9467,7 @@ UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
|
|||
NonTemplateTarget = TargetTD->getTemplatedDecl();
|
||||
|
||||
UsingShadowDecl *Shadow;
|
||||
if (!isa<ConceptDecl>(Target) && isa<CXXConstructorDecl>(NonTemplateTarget)) {
|
||||
if (isa<CXXConstructorDecl>(NonTemplateTarget)) {
|
||||
bool IsVirtualBase =
|
||||
isVirtualDirectBase(cast<CXXRecordDecl>(CurContext),
|
||||
UD->getQualifier()->getAsRecordDecl());
|
||||
|
|
|
@ -232,11 +232,9 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
|
|||
} else {
|
||||
assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) ||
|
||||
isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD) ||
|
||||
isa<BuiltinTemplateDecl>(TD) || isa<ConceptDecl>(TD));
|
||||
isa<BuiltinTemplateDecl>(TD));
|
||||
TemplateKind =
|
||||
isa<VarTemplateDecl>(TD) ? TNK_Var_template :
|
||||
isa<ConceptDecl>(TD) ? TNK_Concept_template :
|
||||
TNK_Type_template;
|
||||
isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3036,8 +3034,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
|
|||
|
||||
TemplateDecl *Template = Name.getAsTemplateDecl();
|
||||
if (!Template || isa<FunctionTemplateDecl>(Template) ||
|
||||
isa<VarTemplateDecl>(Template) ||
|
||||
isa<ConceptDecl>(Template)) {
|
||||
isa<VarTemplateDecl>(Template)) {
|
||||
// We might have a substituted template template parameter pack. If so,
|
||||
// build a template specialization type for it.
|
||||
if (Name.getAsSubstTemplateTemplateParmPack())
|
||||
|
@ -3991,18 +3988,6 @@ Sema::CheckVarTemplateId(const CXXScopeSpec &SS,
|
|||
/*FoundD=*/nullptr, TemplateArgs);
|
||||
}
|
||||
|
||||
ExprResult
|
||||
Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
|
||||
const DeclarationNameInfo &NameInfo,
|
||||
ConceptDecl *Template,
|
||||
SourceLocation TemplateLoc,
|
||||
const TemplateArgumentListInfo *TemplateArgs) {
|
||||
// TODO: Do concept specialization here.
|
||||
Diag(Template->getLocation(), diag::err_concept_feature_unimplemented)
|
||||
<< "can not form concept template-id";
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
|
||||
SourceLocation TemplateKWLoc,
|
||||
LookupResult &R,
|
||||
|
@ -7713,61 +7698,6 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,
|
|||
return NewDecl;
|
||||
}
|
||||
|
||||
ConceptDecl *Sema::ActOnConceptDefinition(Scope *S,
|
||||
MultiTemplateParamsArg TemplateParameterLists, IdentifierInfo *Name,
|
||||
SourceLocation NameLoc, Expr *ConstraintExpr) {
|
||||
// C++2a [temp.concept]p3:
|
||||
// A concept-definition shall appear in the global scope or in a namespace
|
||||
// scope.
|
||||
assert(
|
||||
CurContext->isFileContext() &&
|
||||
"We check during parsing that 'concept's only occur at namespace scope");
|
||||
|
||||
// Forbid any prior declaration of this name within the current namespace.
|
||||
LookupResult Previous(*this,
|
||||
DeclarationNameInfo(DeclarationName(Name), NameLoc),
|
||||
LookupOrdinaryName);
|
||||
LookupName(Previous, S);
|
||||
if (!Previous.empty()) {
|
||||
const NamedDecl *PrevDecl = Previous.getRepresentativeDecl();
|
||||
if (PrevDecl->getDeclContext()->Equals(CurContext)) {
|
||||
if (Previous.isSingleResult() &&
|
||||
isa<ConceptDecl>(Previous.getFoundDecl())) {
|
||||
Diag(NameLoc, diag::err_redefinition) << Name;
|
||||
} else {
|
||||
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
|
||||
}
|
||||
Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ConceptDecl *NewDecl = ConceptDecl::Create(Context, CurContext, NameLoc,
|
||||
Name, TemplateParameterLists[0],
|
||||
ConstraintExpr);
|
||||
|
||||
if (!NewDecl)
|
||||
return nullptr;
|
||||
|
||||
if (NewDecl->getAssociatedConstraints()) {
|
||||
// C++2a [temp.concept]p4:
|
||||
// A concept shall not have associated constraints.
|
||||
// TODO: Make a test once we have actual associated constraints.
|
||||
Diag(NameLoc, diag::err_concept_no_associated_constraints);
|
||||
NewDecl->setInvalidDecl();
|
||||
}
|
||||
|
||||
assert((S->isTemplateParamScope() || !TemplateParameterLists[0]->size()) &&
|
||||
"Not in template param scope?");
|
||||
assert(S->getParent() && !S->getParent()->isTemplateParamScope() &&
|
||||
"Parent scope should exist and not be template parameter.");
|
||||
|
||||
ActOnDocumentableDecl(NewDecl);
|
||||
PushOnScopeChains(NewDecl, S->getParent(), /*AddToContext=*/true);
|
||||
|
||||
return NewDecl;
|
||||
}
|
||||
|
||||
/// \brief Strips various properties off an implicit instantiation
|
||||
/// that has just been explicitly specialized.
|
||||
static void StripImplicitInstantiation(NamedDecl *D) {
|
||||
|
|
|
@ -3073,11 +3073,6 @@ Decl *TemplateDeclInstantiator::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Decl *TemplateDeclInstantiator::VisitConceptDecl(ConceptDecl *D) {
|
||||
llvm_unreachable("Concept definitions cannot reside inside a template");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Decl *TemplateDeclInstantiator::VisitDecl(Decl *D) {
|
||||
llvm_unreachable("Unexpected decl");
|
||||
}
|
||||
|
|
|
@ -313,7 +313,6 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
|
|||
case Decl::BuiltinTemplate:
|
||||
case Decl::Decomposition:
|
||||
case Decl::Binding:
|
||||
case Decl::Concept:
|
||||
return false;
|
||||
|
||||
// These indirectly derive from Redeclarable<T> but are not actually
|
||||
|
|
|
@ -381,7 +381,6 @@ namespace clang {
|
|||
void VisitBindingDecl(BindingDecl *BD);
|
||||
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
|
||||
DeclID VisitTemplateDecl(TemplateDecl *D);
|
||||
void VisitConceptDecl(ConceptDecl *D);
|
||||
RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
|
||||
void VisitClassTemplateDecl(ClassTemplateDecl *D);
|
||||
void VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D);
|
||||
|
@ -2032,11 +2031,6 @@ DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
|
|||
return PatternID;
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitConceptDecl(ConceptDecl *D) {
|
||||
VisitTemplateDecl(D);
|
||||
D->setConstraintExpr(Record.readExpr());
|
||||
}
|
||||
|
||||
ASTDeclReader::RedeclarableResult
|
||||
ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
||||
RedeclarableResult Redecl = VisitRedeclarable(D);
|
||||
|
@ -3601,9 +3595,6 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
|
|||
case DECL_TYPE_ALIAS_TEMPLATE:
|
||||
D = TypeAliasTemplateDecl::CreateDeserialized(Context, ID);
|
||||
break;
|
||||
case DECL_CONCEPT:
|
||||
D = ConceptDecl::CreateDeserialized(Context, ID);
|
||||
break;
|
||||
case DECL_STATIC_ASSERT:
|
||||
D = StaticAssertDecl::CreateDeserialized(Context, ID);
|
||||
break;
|
||||
|
|
|
@ -1280,7 +1280,6 @@ void ASTWriter::WriteBlockInfoBlock() {
|
|||
RECORD(DECL_TEMPLATE_TYPE_PARM);
|
||||
RECORD(DECL_NON_TYPE_TEMPLATE_PARM);
|
||||
RECORD(DECL_TEMPLATE_TEMPLATE_PARM);
|
||||
RECORD(DECL_CONCEPT);
|
||||
RECORD(DECL_TYPE_ALIAS_TEMPLATE);
|
||||
RECORD(DECL_STATIC_ASSERT);
|
||||
RECORD(DECL_CXX_BASE_SPECIFIERS);
|
||||
|
|
|
@ -102,7 +102,6 @@ namespace clang {
|
|||
void VisitBindingDecl(BindingDecl *D);
|
||||
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
|
||||
void VisitTemplateDecl(TemplateDecl *D);
|
||||
void VisitConceptDecl(ConceptDecl *D);
|
||||
void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
|
||||
void VisitClassTemplateDecl(ClassTemplateDecl *D);
|
||||
void VisitVarTemplateDecl(VarTemplateDecl *D);
|
||||
|
@ -1396,12 +1395,6 @@ void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
|
|||
Record.AddTemplateParameterList(D->getTemplateParameters());
|
||||
}
|
||||
|
||||
void ASTDeclWriter::VisitConceptDecl(ConceptDecl *D) {
|
||||
VisitTemplateDecl(D);
|
||||
Record.AddStmt(D->getConstraintExpr());
|
||||
Code = serialization::DECL_CONCEPT;
|
||||
}
|
||||
|
||||
void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
||||
VisitRedeclarable(D);
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
// Support parsing of concepts
|
||||
// Disabled for now.
|
||||
// expected-no-diagnostics
|
||||
|
||||
// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
|
||||
// template<typename T> concept C1 = true;
|
|
@ -1,83 +0,0 @@
|
|||
// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -verify %s
|
||||
// Support parsing of concepts
|
||||
|
||||
concept X; //expected-error {{must be a template}}
|
||||
|
||||
template<typename T> concept C1 = true; //expected-note{{declared here}} <-- previous declaration
|
||||
|
||||
template<typename T> concept C1 = true; // expected-error {{redefinition of 'C1'}}
|
||||
|
||||
template<concept T> concept D1 = true; // expected-error {{'concept' can only appear in namespace scope}} \
|
||||
expected-error {{expected template parameter}}
|
||||
|
||||
template<> concept X = true; // expected-error {{cannot be explicitly specialized}}
|
||||
|
||||
namespace ns1 {
|
||||
template<> concept D1 = true; // expected-error {{cannot be explicitly specialized}}
|
||||
template<typename T> const concept C1 = true; //expected-error{{cannot combine with}}
|
||||
namespace ns12 {
|
||||
template<typename T> decltype(T{}) concept C2 = true; //expected-error{{cannot combine with}}
|
||||
template<typename T> bool concept C3 = true; //expected-error{{cannot combine with}}
|
||||
template<typename T> unsigned concept C4 = true; //expected-error{{cannot combine with}}
|
||||
template<typename T> short concept C5 = true; //expected-error{{cannot combine with}}
|
||||
template<typename T> typedef concept C6 = true; //expected-error{{cannot combine with}}
|
||||
}
|
||||
template<class> concept
|
||||
const //expected-error{{expected concept name}}
|
||||
C2 = true;
|
||||
|
||||
void f() {
|
||||
concept X; //expected-error{{'concept' can only appear in namespace scope}}
|
||||
}
|
||||
template<concept X, //expected-error{{'concept' can only appear in namespace scope}} \
|
||||
expected-error {{expected template parameter}}
|
||||
int J> void f();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
concept [[test]] X2 [[test2]] = T::value; //expected-error2{{attribute list cannot appear here}}
|
||||
|
||||
namespace ns2 {
|
||||
template<class T>
|
||||
concept [[test]] X2 [[test2]] = T::value; //expected-error2{{attribute list cannot appear here}}
|
||||
|
||||
}
|
||||
|
||||
namespace ns3 {
|
||||
template<typename T> concept C1 = true;
|
||||
|
||||
namespace ns1 {
|
||||
using ns3::C1; //expected-note{{declared here}}
|
||||
template<typename T> concept C1 = true; // expected-error {{redefinition of 'C1'}}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// template<typename T> concept C2 = 0.f; // expected error {{constraint expression must be 'bool'}}
|
||||
|
||||
struct S1 {
|
||||
template<typename T> concept C1 = true; // expected-error {{can only appear in namespace scope}}
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
template<typename B>
|
||||
concept C4 = true; // expected-error {{extraneous template parameter list in concept definition}}
|
||||
|
||||
template<typename T> concept C5 = true; // expected-note {{previous}} expected-note {{previous}}
|
||||
int C5; // expected-error {{redefinition}}
|
||||
struct C5 {}; // expected-error {{redefinition}}
|
||||
|
||||
struct C6 {}; //expected-note{{declared here}} <-- previous declaration
|
||||
template<typename T> concept C6 = true; // expected-error {{redefinition of 'C6' as different kind of symbol}}
|
||||
|
||||
namespace thing {};
|
||||
|
||||
template<typename T> concept thing::C7 = true; // expected-error {{concepts must be defined in their own namespace}}
|
||||
|
||||
|
||||
namespace ns5 {
|
||||
}
|
||||
|
||||
// TODO: Add test to prevent explicit specialization, partial specialization
|
||||
// and explicit instantiation of concepts.
|
|
@ -6173,7 +6173,6 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
|
|||
case Decl::PragmaComment:
|
||||
case Decl::PragmaDetectMismatch:
|
||||
case Decl::UsingPack:
|
||||
case Decl::Concept:
|
||||
return C;
|
||||
|
||||
// Declaration kinds that don't make any sense here, but are
|
||||
|
|
Loading…
Reference in New Issue