Author: rsmith Date: Mon Mar 7 18:32:55 2016 New Revision: 262881 URL: http://llvm.org/viewvc/llvm-project?rev=262881&view=rev Log: P0188R1: add support for standard [[fallthrough]] attribute. This is almost exactly the same as clang's existing [[clang::fallthrough]] attribute, which has been updated to have the same semantics. The one significant difference is that [[fallthrough]] is ill-formed if it's not used immediately before a switch label (even when -Wimplicit-fallthrough is disabled). To support that, we now build a CFG of any function that uses a '[[fallthrough]];' statement to check.
In passing, fix some bugs with our support for statement attributes -- in particular, diagnose their use on declarations, rather than asserting. Modified: cfe/trunk/include/clang/AST/Attr.h cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/include/clang/Basic/AttrDocs.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Sema/AttributeList.h cfe/trunk/include/clang/Sema/ScopeInfo.h cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp cfe/trunk/lib/Sema/AttributeList.cpp cfe/trunk/lib/Sema/SemaDeclAttr.cpp cfe/trunk/lib/Sema/SemaStmtAttr.cpp cfe/trunk/test/Analysis/cxx11-crashes.cpp cfe/trunk/test/PCH/Inputs/cxx11-statement-attributes.h cfe/trunk/test/PCH/cxx11-statement-attributes.cpp cfe/trunk/test/Parser/cxx0x-attributes.cpp cfe/trunk/test/SemaCXX/for-range-examples.cpp cfe/trunk/test/SemaCXX/generalized-deprecated.cpp cfe/trunk/test/SemaCXX/nodiscard.cpp cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-macro.cpp cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp cfe/trunk/test/SemaCXX/switch-implicit-fallthrough.cpp cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp cfe/trunk/www/cxx_status.html Modified: cfe/trunk/include/clang/AST/Attr.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Attr.h (original) +++ cfe/trunk/include/clang/AST/Attr.h Mon Mar 7 18:32:55 2016 @@ -118,6 +118,19 @@ public: bool duplicatesAllowed() const { return DuplicatesAllowed; } }; +class StmtAttr : public Attr { +protected: + StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, + bool IsLateParsed, bool DuplicatesAllowed) + : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {} + +public: + static bool classof(const Attr *A) { + return A->getKind() >= attr::FirstStmtAttr && + A->getKind() <= attr::LastStmtAttr; + } +}; + class InheritableAttr : public Attr { protected: InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Mon Mar 7 18:32:55 2016 @@ -311,6 +311,9 @@ class TypeAttr : Attr { let ASTNode = 0; } +/// A stmt attribute is not processed on a declaration or a type. +class StmtAttr : Attr; + /// An inheritable attribute is inherited by later redeclarations. class InheritableAttr : Attr; @@ -738,8 +741,9 @@ def ExtVectorType : Attr { let Documentation = [Undocumented]; } -def FallThrough : Attr { - let Spellings = [CXX11<"clang", "fallthrough">]; +def FallThrough : StmtAttr { + let Spellings = [CXX11<"", "fallthrough", 201503>, + CXX11<"clang", "fallthrough">]; // let Subjects = [NullStmt]; let Documentation = [FallthroughDocs]; } Modified: cfe/trunk/include/clang/Basic/AttrDocs.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/AttrDocs.td (original) +++ cfe/trunk/include/clang/Basic/AttrDocs.td Mon Mar 7 18:32:55 2016 @@ -756,9 +756,10 @@ potentially-evaluated discarded-value ex def FallthroughDocs : Documentation { let Category = DocCatStmt; + let Heading = "fallthrough, clang::fallthrough"; let Content = [{ -The ``clang::fallthrough`` attribute is used along with the -``-Wimplicit-fallthrough`` argument to annotate intentional fall-through +The ``fallthrough`` (or ``clang::fallthrough``) attribute is used +to annotate intentional fall-through between switch labels. It can only be applied to a null statement placed at a point of execution between any statement and the next switch label. It is common to mark these places with a specific comment, but this attribute is @@ -769,6 +770,10 @@ control-flow statements like ``break;``, where ``break;`` can, but only if there are no statements on the execution path between it and the next switch label. +By default, Clang does not warn on unannotated fallthrough from one ``switch`` +case to another. Diagnostics on fallthrough without a corresponding annotation +can be enabled with the ``-Wimplicit-fallthrough`` argument. + Here is an example: .. code-block:: c++ Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Mar 7 18:32:55 2016 @@ -2358,8 +2358,10 @@ def warn_cxx11_gnu_attribute_on_type : W def warn_unhandled_ms_attribute_ignored : Warning< "__declspec attribute %0 is not supported">, InGroup<IgnoredAttributes>; -def err_attribute_invalid_on_stmt : Error< +def err_decl_attribute_invalid_on_stmt : Error< "%0 attribute cannot be applied to a statement">; +def err_stmt_attribute_invalid_on_decl : Error< + "%0 attribute cannot be applied to a declaration">; def warn_declspec_attribute_ignored : Warning< "attribute %0 is ignored, place it after " "\"%select{class|struct|interface|union|enum}1\" to apply attribute to " @@ -6592,8 +6594,11 @@ def warn_unused_result : Warning< def warn_unused_volatile : Warning< "expression result unused; assign into a variable to force a volatile load">, InGroup<DiagGroup<"unused-volatile-lvalue">>; -def ext_nodiscard_attr_is_a_cxx1z_extension : ExtWarn< - "use of the 'nodiscard' attribute is a C++1z extension">, InGroup<CXX1z>; + +def ext_cxx14_attr : Extension< + "use of the %0 attribute is a C++14 extension">, InGroup<CXX14>; +def ext_cxx1z_attr : Extension< + "use of the %0 attribute is a C++1z extension">, InGroup<CXX1z>; def warn_unused_comparison : Warning< "%select{%select{|in}1equality|relational}0 comparison result unused">, @@ -7306,13 +7311,12 @@ def note_insert_fallthrough_fixit : Note def note_insert_break_fixit : Note< "insert 'break;' to avoid fall-through">; def err_fallthrough_attr_wrong_target : Error< - "clang::fallthrough attribute is only allowed on empty statements">; + "%0 attribute is only allowed on empty statements">; def note_fallthrough_insert_semi_fixit : Note<"did you forget ';'?">; def err_fallthrough_attr_outside_switch : Error< "fallthrough annotation is outside switch statement">; -def warn_fallthrough_attr_invalid_placement : Warning< - "fallthrough annotation does not directly precede switch label">, - InGroup<ImplicitFallthrough>; +def err_fallthrough_attr_invalid_placement : Error< + "fallthrough annotation does not directly precede switch label">; def warn_fallthrough_attr_unreachable : Warning< "fallthrough annotation in unreachable code">, InGroup<ImplicitFallthrough>; @@ -7678,9 +7682,6 @@ def err_asm_naked_this_ref : Error< def err_asm_naked_parm_ref : Error< "parameter references not allowed in naked functions">; -def ext_deprecated_attr_is_a_cxx14_extension : ExtWarn< - "use of the 'deprecated' attribute is a C++14 extension">, InGroup<CXX14>; - // OpenCL warnings and errors. def err_invalid_astype_of_different_size : Error< "invalid reinterpretation: sizes of %0 and %1 must match">; Modified: cfe/trunk/include/clang/Sema/AttributeList.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/AttributeList.h (original) +++ cfe/trunk/include/clang/Sema/AttributeList.h Mon Mar 7 18:32:55 2016 @@ -491,6 +491,7 @@ public: bool isTargetSpecificAttr() const; bool isTypeAttr() const; + bool isStmtAttr() const; bool hasCustomParsing() const; unsigned getMinArgs() const; Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/ScopeInfo.h (original) +++ cfe/trunk/include/clang/Sema/ScopeInfo.h Mon Mar 7 18:32:55 2016 @@ -107,6 +107,9 @@ public: /// \brief True if current scope is for OpenMP declare reduction combiner. bool HasOMPDeclareReductionCombiner; + /// \brief Whether there is a fallthrough statement in this function. + bool HasFallthroughStmt : 1; + /// A flag that is set when parsing a method that must call super's /// implementation, such as \c -dealloc, \c -finalize, or any method marked /// with \c __attribute__((objc_requires_super)). @@ -348,6 +351,10 @@ public: HasOMPDeclareReductionCombiner = true; } + void setHasFallthroughStmt() { + HasFallthroughStmt = true; + } + void setHasCXXTry(SourceLocation TryLoc) { setHasBranchProtectedScope(); FirstCXXTryLoc = TryLoc; @@ -371,6 +378,7 @@ public: HasIndirectGoto(false), HasDroppedStmt(false), HasOMPDeclareReductionCombiner(false), + HasFallthroughStmt(false), ObjCShouldCallSuper(false), ObjCIsDesignatedInit(false), ObjCWarnForNoDesignatedInitChain(false), Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original) +++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Mon Mar 7 18:32:55 2016 @@ -1071,6 +1071,34 @@ namespace { }; } // anonymous namespace +static StringRef getFallthroughAttrSpelling(Preprocessor &PP, + SourceLocation Loc) { + TokenValue FallthroughTokens[] = { + tok::l_square, tok::l_square, + PP.getIdentifierInfo("fallthrough"), + tok::r_square, tok::r_square + }; + + TokenValue ClangFallthroughTokens[] = { + tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"), + tok::coloncolon, PP.getIdentifierInfo("fallthrough"), + tok::r_square, tok::r_square + }; + + bool PreferClangAttr = !PP.getLangOpts().CPlusPlus1z; + + StringRef MacroName; + if (PreferClangAttr) + MacroName = PP.getLastMacroWithSpelling(Loc, ClangFallthroughTokens); + if (MacroName.empty()) + MacroName = PP.getLastMacroWithSpelling(Loc, FallthroughTokens); + if (MacroName.empty() && !PreferClangAttr) + MacroName = PP.getLastMacroWithSpelling(Loc, ClangFallthroughTokens); + if (MacroName.empty()) + MacroName = PreferClangAttr ? "[[clang::fallthrough]]" : "[[fallthrough]]"; + return MacroName; +} + static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, bool PerFunction) { // Only perform this analysis when using C++11. There is no good workflow @@ -1129,15 +1157,7 @@ static void DiagnoseSwitchLabelsFallthro } if (!(B->empty() && Term && isa<BreakStmt>(Term))) { Preprocessor &PP = S.getPreprocessor(); - TokenValue Tokens[] = { - tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"), - tok::coloncolon, PP.getIdentifierInfo("fallthrough"), - tok::r_square, tok::r_square - }; - StringRef AnnotationSpelling = "[[clang::fallthrough]]"; - StringRef MacroName = PP.getLastMacroWithSpelling(L, Tokens); - if (!MacroName.empty()) - AnnotationSpelling = MacroName; + StringRef AnnotationSpelling = getFallthroughAttrSpelling(PP, L); SmallString<64> TextToInsert(AnnotationSpelling); TextToInsert += "; "; S.Diag(L, diag::note_insert_fallthrough_fixit) << @@ -1151,7 +1171,7 @@ static void DiagnoseSwitchLabelsFallthro } for (const auto *F : FM.getFallthroughStmts()) - S.Diag(F->getLocStart(), diag::warn_fallthrough_attr_invalid_placement); + S.Diag(F->getLocStart(), diag::err_fallthrough_attr_invalid_placement); } static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM, @@ -2038,7 +2058,8 @@ AnalysisBasedWarnings::IssueWarnings(sem !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getLocStart()); bool FallThroughDiagPerFunction = !Diags.isIgnored( diag::warn_unannotated_fallthrough_per_function, D->getLocStart()); - if (FallThroughDiagFull || FallThroughDiagPerFunction) { + if (FallThroughDiagFull || FallThroughDiagPerFunction || + fscope->HasFallthroughStmt) { DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull); } Modified: cfe/trunk/lib/Sema/AttributeList.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AttributeList.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/lib/Sema/AttributeList.cpp (original) +++ cfe/trunk/lib/Sema/AttributeList.cpp Mon Mar 7 18:32:55 2016 @@ -159,6 +159,7 @@ struct ParsedAttrInfo { unsigned HasCustomParsing : 1; unsigned IsTargetSpecific : 1; unsigned IsType : 1; + unsigned IsStmt : 1; unsigned IsKnownToGCC : 1; bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr, @@ -204,6 +205,10 @@ bool AttributeList::isTypeAttr() const { return getInfo(*this).IsType; } +bool AttributeList::isStmtAttr() const { + return getInfo(*this).IsStmt; +} + bool AttributeList::existsInTarget(const TargetInfo &Target) const { return getInfo(*this).ExistsInTarget(Target); } Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Mon Mar 7 18:32:55 2016 @@ -2467,7 +2467,7 @@ static void handleWarnUnusedResult(Sema // about using it as an extension. if (!S.getLangOpts().CPlusPlus1z && Attr.isCXX11Attribute() && !Attr.getScopeName()) - S.Diag(Attr.getLoc(), diag::ext_nodiscard_attr_is_a_cxx1z_extension); + S.Diag(Attr.getLoc(), diag::ext_cxx1z_attr) << Attr.getName(); D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getRange(), S.Context, @@ -5072,7 +5072,7 @@ static void handleDeprecatedAttr(Sema &S if (!S.getLangOpts().CPlusPlus14) if (Attr.isCXX11Attribute() && !(Attr.hasScope() && Attr.getScopeName()->isStr("gnu"))) - S.Diag(Attr.getLoc(), diag::ext_deprecated_attr_is_a_cxx14_extension); + S.Diag(Attr.getLoc(), diag::ext_cxx14_attr) << Attr.getName(); handleAttrWithMessage<DeprecatedAttr>(S, D, Attr); } @@ -5234,8 +5234,13 @@ static void ProcessDeclAttribute(Sema &S switch (Attr.getKind()) { default: - // Type attributes are handled elsewhere; silently move on. - assert(Attr.isTypeAttr() && "Non-type attribute not handled"); + if (!Attr.isStmtAttr()) { + // Type attributes are handled elsewhere; silently move on. + assert(Attr.isTypeAttr() && "Non-type attribute not handled"); + break; + } + S.Diag(Attr.getLoc(), diag::err_stmt_attribute_invalid_on_decl) + << Attr.getName() << D->getLocation(); break; case AttributeList::AT_Interrupt: handleInterruptAttr(S, D, Attr); Modified: cfe/trunk/lib/Sema/SemaStmtAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAttr.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaStmtAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaStmtAttr.cpp Mon Mar 7 18:32:55 2016 @@ -25,9 +25,11 @@ using namespace sema; static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A, SourceRange Range) { + FallThroughAttr Attr(A.getRange(), S.Context, + A.getAttributeSpellingListIndex()); if (!isa<NullStmt>(St)) { S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target) - << St->getLocStart(); + << Attr.getSpelling() << St->getLocStart(); if (isa<SwitchCase>(St)) { SourceLocation L = S.getLocForEndOfToken(Range.getEnd()); S.Diag(L, diag::note_fallthrough_insert_semi_fixit) @@ -35,12 +37,20 @@ static Attr *handleFallThroughAttr(Sema } return nullptr; } - if (S.getCurFunction()->SwitchStack.empty()) { + auto *FnScope = S.getCurFunction(); + if (FnScope->SwitchStack.empty()) { S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_outside_switch); return nullptr; } - return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context, - A.getAttributeSpellingListIndex()); + + // If this is spelled as the standard C++1z attribute, but not in C++1z, warn + // about using it as an extension. + if (!S.getLangOpts().CPlusPlus1z && A.isCXX11Attribute() && + !A.getScopeName()) + S.Diag(A.getLoc(), diag::ext_cxx1z_attr) << A.getName(); + + FnScope->setHasFallthroughStmt(); + return ::new (S.Context) auto(Attr); } static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A, @@ -266,7 +276,7 @@ static Attr *ProcessStmtAttribute(Sema & default: // if we're here, then we parsed a known attribute, but didn't recognize // it as a statement attribute => it is declaration attribute - S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt) + S.Diag(A.getRange().getBegin(), diag::err_decl_attribute_invalid_on_stmt) << A.getName() << St->getLocStart(); return nullptr; } Modified: cfe/trunk/test/Analysis/cxx11-crashes.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx11-crashes.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/test/Analysis/cxx11-crashes.cpp (original) +++ cfe/trunk/test/Analysis/cxx11-crashes.cpp Mon Mar 7 18:32:55 2016 @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core -std=c++11 -verify %s -// expected-no-diagnostics // radar://11485149, PR12871 class PlotPoint { @@ -91,6 +90,6 @@ void test() { void fallthrough() { switch (1) { case 1: - [[clang::fallthrough]]; + [[clang::fallthrough]]; // expected-error {{does not directly precede}} } } Modified: cfe/trunk/test/PCH/Inputs/cxx11-statement-attributes.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/Inputs/cxx11-statement-attributes.h?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/test/PCH/Inputs/cxx11-statement-attributes.h (original) +++ cfe/trunk/test/PCH/Inputs/cxx11-statement-attributes.h Mon Mar 7 18:32:55 2016 @@ -7,7 +7,8 @@ int f(int n) { [[clang::fallthrough]]; // This shouldn't generate a warning. case 1: n += 20; - [[clang::fallthrough]]; // This should generate a warning: "fallthrough annotation does not directly precede switch label". + case 2: // This should generate a warning: "unannotated fallthrough" + n += 35; break; } return n; Modified: cfe/trunk/test/PCH/cxx11-statement-attributes.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx11-statement-attributes.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/test/PCH/cxx11-statement-attributes.cpp (original) +++ cfe/trunk/test/PCH/cxx11-statement-attributes.cpp Mon Mar 7 18:32:55 2016 @@ -1,10 +1,15 @@ // Sanity check. // RUN: %clang_cc1 -include %S/Inputs/cxx11-statement-attributes.h -std=c++11 -Wimplicit-fallthrough -fsyntax-only %s -o - -verify +// RUN: %clang_cc1 -include %S/Inputs/cxx11-statement-attributes.h -std=c++1z -Wimplicit-fallthrough -fsyntax-only %s -o - -verify // Run the same tests, this time with the attributes loaded from the PCH file. // RUN: %clang_cc1 -x c++-header -emit-pch -std=c++11 -o %t %S/Inputs/cxx11-statement-attributes.h // RUN: %clang_cc1 -include-pch %t -std=c++11 -Wimplicit-fallthrough -fsyntax-only %s -o - -verify +// RUN: %clang_cc1 -x c++-header -emit-pch -std=c++1z -o %t %S/Inputs/cxx11-statement-attributes.h +// RUN: %clang_cc1 -include-pch %t -std=c++1z -Wimplicit-fallthrough -fsyntax-only %s -o - -verify -// expected-warning@Inputs/cxx11-statement-attributes.h:10 {{fallthrough annotation does not directly precede switch label}} +// expected-warning@Inputs/cxx11-statement-attributes.h:10 {{unannotated fall-through}} +// expected-note-re@Inputs/cxx11-statement-attributes.h:10 {{insert '[[{{(clang::)?}}fallthrough]];'}} +// expected-note@Inputs/cxx11-statement-attributes.h:10 {{insert 'break;'}} void g(int n) { f<1>(n); // expected-note {{in instantiation of function template specialization 'f<1>' requested here}} Modified: cfe/trunk/test/Parser/cxx0x-attributes.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/test/Parser/cxx0x-attributes.cpp (original) +++ cfe/trunk/test/Parser/cxx0x-attributes.cpp Mon Mar 7 18:32:55 2016 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -Wc++14-compat %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -Wc++14-compat -Wc++14-extensions -Wc++1z-extensions %s // Need std::initializer_list namespace std { @@ -347,6 +347,18 @@ deprecated ]] void bad(); } +int fallthru(int n) { + switch (n) { + case 0: + n += 5; + [[fallthrough]]; // expected-warning {{use of the 'fallthrough' attribute is a C++1z extension}} + case 1: + n *= 2; + break; + } + return n; +} + #define attr_name bitand #define attr_name_2(x) x #define attr_name_3(x, y) x##y Modified: cfe/trunk/test/SemaCXX/for-range-examples.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/for-range-examples.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/for-range-examples.cpp (original) +++ cfe/trunk/test/SemaCXX/for-range-examples.cpp Mon Mar 7 18:32:55 2016 @@ -226,7 +226,7 @@ namespace test7 { // we check the alignment attribute before we perform the auto // deduction. for (d alignas(1) : arr) {} // expected-error {{requires type for loop variable}} - for (e [[deprecated]] : arr) { e = 0; } // expected-warning{{use of the 'deprecated' attribute is a C++14 extension}} expected-warning {{deprecated}} expected-note {{here}} expected-error {{requires type for loop variable}} + for (e [[deprecated]] : arr) { e = 0; } // expected-warning {{deprecated}} expected-note {{here}} expected-error {{requires type for loop variable}} } } Modified: cfe/trunk/test/SemaCXX/generalized-deprecated.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/generalized-deprecated.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/generalized-deprecated.cpp (original) +++ cfe/trunk/test/SemaCXX/generalized-deprecated.cpp Mon Mar 7 18:32:55 2016 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -fms-extensions -Wno-deprecated %s +// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -fms-extensions -Wno-deprecated -Wc++14-extensions %s // NOTE: use -Wno-deprecated to avoid cluttering the output with deprecated // warnings Modified: cfe/trunk/test/SemaCXX/nodiscard.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/nodiscard.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/nodiscard.cpp (original) +++ cfe/trunk/test/SemaCXX/nodiscard.cpp Mon Mar 7 18:32:55 2016 @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++1z -verify %s -// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -DEXT %s +// RUN: %clang_cc1 -fsyntax-only -std=c++1z -verify -Wc++1z-extensions %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -DEXT -Wc++1z-extensions %s #if !defined(EXT) static_assert(__has_cpp_attribute(nodiscard) == 201603); Modified: cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-macro.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-macro.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-macro.cpp (original) +++ cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-macro.cpp Mon Mar 7 18:32:55 2016 @@ -1,4 +1,8 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wimplicit-fallthrough -DCOMMAND_LINE_FALLTHROUGH=[[clang::fallthrough]] %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wimplicit-fallthrough -DCLANG_PREFIX -DCOMMAND_LINE_FALLTHROUGH=[[clang::fallthrough]] -DUNCHOSEN=[[fallthrough]] %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wimplicit-fallthrough -DCOMMAND_LINE_FALLTHROUGH=[[fallthrough]] %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z -Wimplicit-fallthrough -DCLANG_PREFIX -DCOMMAND_LINE_FALLTHROUGH=[[clang::fallthrough]] %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z -Wimplicit-fallthrough -DCOMMAND_LINE_FALLTHROUGH=[[clang::fallthrough]] %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z -Wimplicit-fallthrough -DCOMMAND_LINE_FALLTHROUGH=[[fallthrough]] -DUNCHOSEN=[[clang::fallthrough]] %s int fallthrough_compatibility_macro_from_command_line(int n) { switch (n) { @@ -10,15 +14,12 @@ int fallthrough_compatibility_macro_from return n; } -#ifdef __clang__ -#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") +#ifdef CLANG_PREFIX #define COMPATIBILITY_FALLTHROUGH [ [ /* test */ clang /* test */ \ :: fallthrough ] ] // testing whitespace and comments in macro definition -#endif -#endif - -#ifndef COMPATIBILITY_FALLTHROUGH -#define COMPATIBILITY_FALLTHROUGH do { } while (0) +#else +#define COMPATIBILITY_FALLTHROUGH [ [ /* test */ /* test */ \ + fallthrough ] ] // testing whitespace and comments in macro definition #endif int fallthrough_compatibility_macro_from_source(int n) { @@ -32,7 +33,11 @@ int fallthrough_compatibility_macro_from } // Deeper macro substitution +#ifdef CLANG_PREFIX #define M1 [[clang::fallthrough]] +#else +#define M1 [[fallthrough]] +#endif #ifdef __clang__ #define M2 M1 #else @@ -59,12 +64,17 @@ int fallthrough_compatibility_macro_in_m #undef M2 #undef COMPATIBILITY_FALLTHROUGH #undef COMMAND_LINE_FALLTHROUGH +#undef UNCHOSEN int fallthrough_compatibility_macro_undefined(int n) { switch (n) { case 0: n = n * 20; +#if __cplusplus <= 201402L case 1: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} +#else + case 1: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} +#endif ; } #define TOO_LATE [[clang::fallthrough]] @@ -83,7 +93,11 @@ int fallthrough_compatibility_macro_hist case 0: n = n * 20; #undef MACRO_WITH_HISTORY +#if __cplusplus <= 201402L case 1: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} +#else + case 1: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} +#endif ; #define MACRO_WITH_HISTORY [[clang::fallthrough]] } Modified: cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp (original) +++ cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp Mon Mar 7 18:32:55 2016 @@ -41,9 +41,8 @@ int fallthrough2(int n) { void unscoped(int n) { switch (n % 2) { case 0: - // FIXME: This should be typo-corrected, probably. - [[fallthrough]]; // expected-warning{{unknown attribute 'fallthrough' ignored}} - case 2: // expected-warning{{unannotated fall-through}} expected-note{{clang::fallthrough}} expected-note{{break;}} + [[fallthrough]]; + case 2: [[clang::fallthrough]]; case 1: break; Modified: cfe/trunk/test/SemaCXX/switch-implicit-fallthrough.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/switch-implicit-fallthrough.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/switch-implicit-fallthrough.cpp (original) +++ cfe/trunk/test/SemaCXX/switch-implicit-fallthrough.cpp Mon Mar 7 18:32:55 2016 @@ -179,18 +179,15 @@ void fallthrough_cfgblock_with_null_succ int fallthrough_position(int n) { switch (n) { - [[clang::fallthrough]]; // expected-warning{{fallthrough annotation does not directly precede switch label}} n += 300; [[clang::fallthrough]]; // expected-warning{{fallthrough annotation in unreachable code}} case 221: - [[clang::fallthrough]]; // expected-warning{{fallthrough annotation does not directly precede switch label}} return 1; [[clang::fallthrough]]; // expected-warning{{fallthrough annotation in unreachable code}} case 222: - [[clang::fallthrough]]; // expected-warning{{fallthrough annotation does not directly precede switch label}} n += 400; case 223: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} - [[clang::fallthrough]]; // expected-warning{{fallthrough annotation does not directly precede switch label}} + ; } long p = static_cast<long>(n) * n; @@ -282,6 +279,23 @@ namespace PR18983 { } } +int fallthrough_placement_error(int n) { + switch (n) { + [[clang::fallthrough]]; // expected-warning{{fallthrough annotation in unreachable code}} + n += 300; + case 221: + [[clang::fallthrough]]; // expected-error{{fallthrough annotation does not directly precede switch label}} + return 1; + case 222: + [[clang::fallthrough]]; // expected-error{{fallthrough annotation does not directly precede switch label}} + n += 400; + [[clang::fallthrough]]; + case 223: + [[clang::fallthrough]]; // expected-error{{fallthrough annotation does not directly precede switch label}} + } + return n; +} + int fallthrough_targets(int n) { [[clang::fallthrough]]; // expected-error{{fallthrough annotation is outside switch statement}} Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original) +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Mon Mar 7 18:32:55 2016 @@ -1761,6 +1761,7 @@ namespace { static const AttrClassDescriptor AttrClassDescriptors[] = { { "ATTR", "Attr" }, + { "STMT_ATTR", "StmtAttr" }, { "INHERITABLE_ATTR", "InheritableAttr" }, { "INHERITABLE_PARAM_ATTR", "InheritableParamAttr" }, { "PARAMETER_ABI_ATTR", "ParameterABIAttr" } @@ -2806,6 +2807,7 @@ void EmitClangAttrParsedAttrImpl(RecordK SS << ", " << I->second->getValueAsBit("HasCustomParsing"); SS << ", " << I->second->isSubClassOf("TargetSpecificAttr"); SS << ", " << I->second->isSubClassOf("TypeAttr"); + SS << ", " << I->second->isSubClassOf("StmtAttr"); SS << ", " << IsKnownToGCC(*I->second); SS << ", " << GenerateAppertainsTo(*I->second, OS); SS << ", " << GenerateLangOptRequirements(*I->second, OS); Modified: cfe/trunk/www/cxx_status.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=262881&r1=262880&r2=262881&view=diff ============================================================================== --- cfe/trunk/www/cxx_status.html (original) +++ cfe/trunk/www/cxx_status.html Mon Mar 7 18:32:55 2016 @@ -629,7 +629,7 @@ as the draft C++1z standard evolves.</p> <tr> <td><tt>[[fallthrough]]</tt> attribute</td> <td><a href="http://wg21.link/p0188r1">P0188R1</a></td> - <td class="none" align="center">No</td> + <td class="full" align="center">SVN</td> </tr> <tr> <td><tt>[[nodiscard]]</tt> attribute</td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits