Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -1973,6 +1973,8 @@ "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< Index: include/clang/Sema/DeclSpec.h =================================================================== --- include/clang/Sema/DeclSpec.h +++ include/clang/Sema/DeclSpec.h @@ -1255,8 +1255,12 @@ /// any. unsigned MutableLoc; - /// \brief The location of the keyword introducing the spec, if any. - unsigned ExceptionSpecLoc; + /// \brief The beginning location of the keyword introducing the spec, if + /// any. + unsigned ExceptionSpecLocBeg; + + /// \brief The end location of the keyword introducing the spec, 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 +1327,16 @@ 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 +1508,7 @@ SourceLocation RestrictQualifierLoc, SourceLocation MutableLoc, ExceptionSpecificationType ESpecType, - SourceLocation ESpecLoc, + SourceRange ESpecRange, ParsedType *Exceptions, SourceRange *ExceptionRanges, unsigned NumExceptions, Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -5612,7 +5612,7 @@ VolatileQualifierLoc, RestrictQualifierLoc, /*MutableLoc=*/SourceLocation(), - ESpecType, ESpecRange.getBegin(), + ESpecType, ESpecRange, DynamicExceptions.data(), DynamicExceptionRanges.data(), DynamicExceptions.size(), Index: lib/Parse/ParseExpr.cpp =================================================================== --- lib/Parse/ParseExpr.cpp +++ lib/Parse/ParseExpr.cpp @@ -2747,7 +2747,7 @@ /*RestrictQualifierLoc=*/NoLoc, /*MutableLoc=*/NoLoc, EST_None, - /*ESpecLoc=*/NoLoc, + /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, Index: lib/Parse/ParseExprCXX.cpp =================================================================== --- lib/Parse/ParseExprCXX.cpp +++ lib/Parse/ParseExprCXX.cpp @@ -1149,7 +1149,7 @@ /*VolatileQualifierLoc=*/NoLoc, /*RestrictQualifierLoc=*/NoLoc, MutableLoc, - ESpecType, ESpecRange.getBegin(), + ESpecType, ESpecRange, DynamicExceptions.data(), DynamicExceptionRanges.data(), DynamicExceptions.size(), @@ -1217,7 +1217,7 @@ /*RestrictQualifierLoc=*/NoLoc, MutableLoc, EST_None, - /*ESpecLoc=*/NoLoc, + /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -177,7 +177,7 @@ SourceLocation MutableLoc, ExceptionSpecificationType ESpecType, - SourceLocation ESpecLoc, + SourceRange ESpecRange, ParsedType *Exceptions, SourceRange *ExceptionRanges, unsigned NumExceptions, @@ -212,7 +212,8 @@ 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; Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -7442,6 +7442,25 @@ 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()) { + SourceRange Range; + if (FPT->hasExceptionSpec() && D.isFunctionDeclarator()) { + Range = D.getFunctionTypeInfo().getExceptionSpecRange(); + PartialDiagnostic PD = + PDiag(diag::err_function_concept_exception_spec); + if (Range.isValid()) { + PD << FixItHint::CreateRemoval(Range); + } + Diag(NewFD->getLocation(), PD); + 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(); @@ -11075,7 +11094,7 @@ /*RestrictQualifierLoc=*/NoLoc, /*MutableLoc=*/NoLoc, EST_None, - /*ESpecLoc=*/NoLoc, + /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -700,7 +700,7 @@ /*VolatileQualifierLoc=*/NoLoc, /*RestrictQualifierLoc=*/NoLoc, /*MutableLoc=*/NoLoc, EST_None, - /*ESpecLoc=*/NoLoc, + /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, @@ -3833,7 +3833,7 @@ // 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) + S.Diag(FTI.getExceptionSpecLocBeg(), diag::err_exception_spec_in_typedef) << (D.getContext() == Declarator::AliasDeclContext || D.getContext() == Declarator::AliasTemplateContext); Index: test/SemaCXX/cxx-concept-declaration.cpp =================================================================== --- test/SemaCXX/cxx-concept-declaration.cpp +++ test/SemaCXX/cxx-concept-declaration.cpp @@ -6,6 +6,9 @@ template concept bool C2 = true; } +template concept bool C3() { return true; } +static_assert(noexcept(C3()), "function concept should be treated as if noexcept(true) specified"); + template concept bool D1(); // expected-error {{function concept declaration must be a definition}} struct B { @@ -23,3 +26,5 @@ template concept bool D6; // expected-error {{variable concept declaration must be initialized}} +template +concept bool D7() throw(int) { return true; } // expected-error {{function concept cannot have exception specification}}