"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<
/// 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
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.
SourceLocation RestrictQualifierLoc,
SourceLocation MutableLoc,
ExceptionSpecificationType ESpecType,
- SourceLocation ESpecLoc,
+ SourceRange ESpecRange,
ParsedType *Exceptions,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
VolatileQualifierLoc,
RestrictQualifierLoc,
/*MutableLoc=*/SourceLocation(),
- ESpecType, ESpecRange.getBegin(),
+ ESpecType, ESpecRange,
DynamicExceptions.data(),
DynamicExceptionRanges.data(),
DynamicExceptions.size(),
/*RestrictQualifierLoc=*/NoLoc,
/*MutableLoc=*/NoLoc,
EST_None,
- /*ESpecLoc=*/NoLoc,
+ /*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
/*VolatileQualifierLoc=*/NoLoc,
/*RestrictQualifierLoc=*/NoLoc,
MutableLoc,
- ESpecType, ESpecRange.getBegin(),
+ ESpecType, ESpecRange,
DynamicExceptions.data(),
DynamicExceptionRanges.data(),
DynamicExceptions.size(),
/*RestrictQualifierLoc=*/NoLoc,
MutableLoc,
EST_None,
- /*ESpecLoc=*/NoLoc,
+ /*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
SourceLocation MutableLoc,
ExceptionSpecificationType
ESpecType,
- SourceLocation ESpecLoc,
+ SourceRange ESpecRange,
ParsedType *Exceptions,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
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;
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();
/*RestrictQualifierLoc=*/NoLoc,
/*MutableLoc=*/NoLoc,
EST_None,
- /*ESpecLoc=*/NoLoc,
+ /*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
/*VolatileQualifierLoc=*/NoLoc,
/*RestrictQualifierLoc=*/NoLoc,
/*MutableLoc=*/NoLoc, EST_None,
- /*ESpecLoc=*/NoLoc,
+ /*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
// 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.
-// 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; }
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 {
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}}