forked from OSchip/llvm-project
Modify DeclaratorChuck::getFunction to be passed an Exception Specification SourceRange
Summary: - Store the exception specification range's begin and end SourceLocation in DeclaratorChuck::FunctionTypeInfo. These SourceLocations can be used in a FixItHint Range. - Add diagnostic; function concept having an exception specification. Reviewers: hubert.reinterpretcast, fraggamuffin, faisalv, aaron.ballman, rsmith Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D11789 llvm-svn: 246005
This commit is contained in:
parent
da9765b966
commit
e23a9a4514
|
@ -1977,6 +1977,8 @@ 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">;
|
||||
|
||||
// C++11 char16_t/char32_t
|
||||
def warn_cxx98_compat_unicode_type : Warning<
|
||||
|
|
|
@ -1255,8 +1255,11 @@ struct DeclaratorChunk {
|
|||
/// any.
|
||||
unsigned MutableLoc;
|
||||
|
||||
/// \brief The location of the keyword introducing the spec, if any.
|
||||
unsigned ExceptionSpecLoc;
|
||||
/// \brief The beginning location of the exception specification, if any.
|
||||
unsigned ExceptionSpecLocBeg;
|
||||
|
||||
/// \brief The end location of the exception specification, if any.
|
||||
unsigned ExceptionSpecLocEnd;
|
||||
|
||||
/// Params - This is a pointer to a new[]'d array of ParamInfo objects that
|
||||
/// describe the parameters specified by this function declarator. null if
|
||||
|
@ -1323,8 +1326,16 @@ struct DeclaratorChunk {
|
|||
return SourceLocation::getFromRawEncoding(RParenLoc);
|
||||
}
|
||||
|
||||
SourceLocation getExceptionSpecLoc() const {
|
||||
return SourceLocation::getFromRawEncoding(ExceptionSpecLoc);
|
||||
SourceLocation getExceptionSpecLocBeg() const {
|
||||
return SourceLocation::getFromRawEncoding(ExceptionSpecLocBeg);
|
||||
}
|
||||
|
||||
SourceLocation getExceptionSpecLocEnd() const {
|
||||
return SourceLocation::getFromRawEncoding(ExceptionSpecLocEnd);
|
||||
}
|
||||
|
||||
SourceRange getExceptionSpecRange() const {
|
||||
return SourceRange(getExceptionSpecLocBeg(), getExceptionSpecLocEnd());
|
||||
}
|
||||
|
||||
/// \brief Retrieve the location of the ref-qualifier, if any.
|
||||
|
@ -1496,7 +1507,7 @@ struct DeclaratorChunk {
|
|||
SourceLocation RestrictQualifierLoc,
|
||||
SourceLocation MutableLoc,
|
||||
ExceptionSpecificationType ESpecType,
|
||||
SourceLocation ESpecLoc,
|
||||
SourceRange ESpecRange,
|
||||
ParsedType *Exceptions,
|
||||
SourceRange *ExceptionRanges,
|
||||
unsigned NumExceptions,
|
||||
|
|
|
@ -5620,7 +5620,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
|
|||
VolatileQualifierLoc,
|
||||
RestrictQualifierLoc,
|
||||
/*MutableLoc=*/SourceLocation(),
|
||||
ESpecType, ESpecRange.getBegin(),
|
||||
ESpecType, ESpecRange,
|
||||
DynamicExceptions.data(),
|
||||
DynamicExceptionRanges.data(),
|
||||
DynamicExceptions.size(),
|
||||
|
|
|
@ -2768,7 +2768,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
|
|||
/*RestrictQualifierLoc=*/NoLoc,
|
||||
/*MutableLoc=*/NoLoc,
|
||||
EST_None,
|
||||
/*ESpecLoc=*/NoLoc,
|
||||
/*ESpecRange=*/SourceRange(),
|
||||
/*Exceptions=*/nullptr,
|
||||
/*ExceptionRanges=*/nullptr,
|
||||
/*NumExceptions=*/0,
|
||||
|
|
|
@ -1149,7 +1149,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
|||
/*VolatileQualifierLoc=*/NoLoc,
|
||||
/*RestrictQualifierLoc=*/NoLoc,
|
||||
MutableLoc,
|
||||
ESpecType, ESpecRange.getBegin(),
|
||||
ESpecType, ESpecRange,
|
||||
DynamicExceptions.data(),
|
||||
DynamicExceptionRanges.data(),
|
||||
DynamicExceptions.size(),
|
||||
|
@ -1217,7 +1217,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
|||
/*RestrictQualifierLoc=*/NoLoc,
|
||||
MutableLoc,
|
||||
EST_None,
|
||||
/*ESpecLoc=*/NoLoc,
|
||||
/*ESpecRange=*/SourceRange(),
|
||||
/*Exceptions=*/nullptr,
|
||||
/*ExceptionRanges=*/nullptr,
|
||||
/*NumExceptions=*/0,
|
||||
|
|
|
@ -177,7 +177,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
|
|||
SourceLocation MutableLoc,
|
||||
ExceptionSpecificationType
|
||||
ESpecType,
|
||||
SourceLocation ESpecLoc,
|
||||
SourceRange ESpecRange,
|
||||
ParsedType *Exceptions,
|
||||
SourceRange *ExceptionRanges,
|
||||
unsigned NumExceptions,
|
||||
|
@ -212,7 +212,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
|
|||
I.Fun.RestrictQualifierLoc = RestrictQualifierLoc.getRawEncoding();
|
||||
I.Fun.MutableLoc = MutableLoc.getRawEncoding();
|
||||
I.Fun.ExceptionSpecType = ESpecType;
|
||||
I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding();
|
||||
I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin().getRawEncoding();
|
||||
I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd().getRawEncoding();
|
||||
I.Fun.NumExceptions = 0;
|
||||
I.Fun.Exceptions = nullptr;
|
||||
I.Fun.NoexceptExpr = nullptr;
|
||||
|
|
|
@ -7476,6 +7476,22 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
NewFD->setInvalidDecl();
|
||||
}
|
||||
|
||||
// C++ Concepts TS [dcl.spec.concept]p1: [...] A function concept shall
|
||||
// have no exception-specification and is treated as if it were specified
|
||||
// with noexcept(true) (15.4). [...]
|
||||
if (const FunctionProtoType *FPT = R->getAs<FunctionProtoType>()) {
|
||||
if (FPT->hasExceptionSpec()) {
|
||||
SourceRange Range;
|
||||
if (D.isFunctionDeclarator())
|
||||
Range = D.getFunctionTypeInfo().getExceptionSpecRange();
|
||||
Diag(NewFD->getLocation(), diag::err_function_concept_exception_spec)
|
||||
<< FixItHint::CreateRemoval(Range);
|
||||
NewFD->setInvalidDecl();
|
||||
} else {
|
||||
Context.adjustExceptionSpec(NewFD, EST_BasicNoexcept);
|
||||
}
|
||||
}
|
||||
|
||||
// C++ Concepts TS [dcl.spec.concept]p2: Every concept definition is
|
||||
// implicity defined to be a constexpr declaration (implicitly inline)
|
||||
NewFD->setImplicitlyInline();
|
||||
|
@ -11123,7 +11139,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
|
|||
/*RestrictQualifierLoc=*/NoLoc,
|
||||
/*MutableLoc=*/NoLoc,
|
||||
EST_None,
|
||||
/*ESpecLoc=*/NoLoc,
|
||||
/*ESpecRange=*/SourceRange(),
|
||||
/*Exceptions=*/nullptr,
|
||||
/*ExceptionRanges=*/nullptr,
|
||||
/*NumExceptions=*/0,
|
||||
|
|
|
@ -700,7 +700,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
|
|||
/*VolatileQualifierLoc=*/NoLoc,
|
||||
/*RestrictQualifierLoc=*/NoLoc,
|
||||
/*MutableLoc=*/NoLoc, EST_None,
|
||||
/*ESpecLoc=*/NoLoc,
|
||||
/*ESpecRange=*/SourceRange(),
|
||||
/*Exceptions=*/nullptr,
|
||||
/*ExceptionRanges=*/nullptr,
|
||||
/*NumExceptions=*/0,
|
||||
|
@ -3833,9 +3833,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
// Exception specs are not allowed in typedefs. Complain, but add it
|
||||
// anyway.
|
||||
if (IsTypedefName && FTI.getExceptionSpecType())
|
||||
S.Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef)
|
||||
<< (D.getContext() == Declarator::AliasDeclContext ||
|
||||
D.getContext() == Declarator::AliasTemplateContext);
|
||||
S.Diag(FTI.getExceptionSpecLocBeg(),
|
||||
diag::err_exception_spec_in_typedef)
|
||||
<< (D.getContext() == Declarator::AliasDeclContext ||
|
||||
D.getContext() == Declarator::AliasTemplateContext);
|
||||
|
||||
// If we see "T var();" or "T var(T());" at block scope, it is probably
|
||||
// an attempt to initialize a variable, not a function declaration.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
|
||||
// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -fcxx-exceptions -x c++ -verify %s
|
||||
|
||||
namespace A {
|
||||
template<typename T> concept bool C1() { return true; }
|
||||
|
@ -6,6 +6,9 @@ namespace A {
|
|||
template<typename T> concept bool C2 = true;
|
||||
}
|
||||
|
||||
template<typename T> concept bool C3() { return (throw 0, true); }
|
||||
static_assert(noexcept(C3<int>()), "function concept should be treated as if noexcept(true) specified");
|
||||
|
||||
template<typename T> concept bool D1(); // expected-error {{function concept declaration must be a definition}}
|
||||
|
||||
struct B {
|
||||
|
@ -23,6 +26,9 @@ concept bool D5 = true; // expected-error {{'concept' can only appear on the def
|
|||
template<typename T>
|
||||
concept bool D6; // expected-error {{variable concept declaration must be initialized}}
|
||||
|
||||
template<typename T>
|
||||
concept bool D7() throw(int) { return true; } // expected-error {{function concept cannot have exception specification}}
|
||||
|
||||
// Tag
|
||||
concept class CC1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
|
||||
concept struct CS1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
|
||||
|
|
Loading…
Reference in New Issue