Tyker updated this revision to Diff 191035.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D59467/new/
https://reviews.llvm.org/D59467
Files:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Parse/ParseDeclCXX.cpp
clang/lib/Parse/ParseStmt.cpp
clang/lib/Sema/SemaStmtAttr.cpp
clang/test/AST/ast-dump-attr.cpp
clang/test/SemaCXX/cxx2a-likely-attr.cpp
Index: clang/test/SemaCXX/cxx2a-likely-attr.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/cxx2a-likely-attr.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++2a
+
+int f(int i) {
+ if (i == 1)
+ {
+ return 0;
+ }
+ else if (i == 2) [[likely]]
+ return 1;
+ return 3;
+}
+
+[[likely]] typedef int n1; // expected-error {{'likely' attribute cannot be applied to a declaration}}
+typedef int [[likely]] n2; // expected-error {{'likely' attribute cannot be applied to types}}
+typedef int n3 [[likely]]; // expected-error {{'likely' attribute cannot be applied to a declaration}}
+
+enum [[likely]] E { // expected-error {{'likely' attribute cannot be applied to a declaration}}
+ One
+};
+
+[[likely]] // expected-error {{'likely' attribute cannot be applied to a declaration}}
+void g(void) {
+ [[likely]] int n; // expected-error {{'likely' attribute cannot be applied to a declaration}}
+ [[likely]] ++n; // expected-error {{likely annotation can't appear here}}
+
+ switch (n) {
+ [[likely]] return; // expected-error {{likely annotation can't appear here}}
+
+ case 0:
+ if (1) [[likely, likely]] // expected-error {{attribute 'likely' cannot appear multiple times in an attribute specifier}}
+ return ;
+ if (1) [[likely(0)]] // expected-error {{attribute 'likely' cannot have an argument list}}
+ return ;
+ break;
+ }
+}
+
Index: clang/test/AST/ast-dump-attr.cpp
===================================================================
--- clang/test/AST/ast-dump-attr.cpp
+++ clang/test/AST/ast-dump-attr.cpp
@@ -23,6 +23,21 @@
// CHECK-NEXT: FallThroughAttr
// CHECK-NEXT: NullStmt
+int TestLikelyAttribute(int i) {
+ if (i == 1) [[likely]] {
+ return 0;
+ } else if (i == 2) [[likely]]
+ return 1;
+ return 2;
+}
+// CHECK: FunctionDecl{{.*}}TestLikelyAttribute
+// CHECK: AttributedStmt
+// CHECK-NEXT: LikelyAttr
+// CHECK-NEXT: IfStmt
+// CHECK: AttributedStmt
+// CHECK-NEXT: LikelyAttr
+// CHECK-NEXT: IfStmt
+
[[clang::warn_unused_result]] int TestCXX11DeclAttr();
// CHECK: FunctionDecl{{.*}}TestCXX11DeclAttr
// CHECK-NEXT: WarnUnusedResultAttr
Index: clang/lib/Sema/SemaStmtAttr.cpp
===================================================================
--- clang/lib/Sema/SemaStmtAttr.cpp
+++ clang/lib/Sema/SemaStmtAttr.cpp
@@ -51,6 +51,21 @@
return ::new (S.Context) auto(Attr);
}
+static Attr *handleLikelyAttr(Sema &S, Stmt *St, const ParsedAttr &A,
+ SourceRange Range) {
+ LikelyAttr Attr(A.getRange(), S.Context,
+ A.getAttributeSpellingListIndex());
+
+ if (!llvm::isa<IfStmt>(St)) {
+ S.Diag(A.getLoc(), diag::err_likely_attr_invalid_placement) << A.getName();
+ }
+
+ if (!S.getLangOpts().CPlusPlus2a && !A.getScopeName())
+ S.Diag(A.getLoc(), diag::ext_cxx2a_attr) << A.getName();
+
+ return ::new (S.Context) auto(Attr);
+}
+
static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
if (A.getNumArgs() < 1) {
@@ -336,6 +351,8 @@
return nullptr;
case ParsedAttr::AT_FallThrough:
return handleFallThroughAttr(S, St, A, Range);
+ case ParsedAttr::AT_Likely:
+ return handleLikelyAttr(S, St, A, Range);
case ParsedAttr::AT_LoopHint:
return handleLoopHintAttr(S, St, A, Range);
case ParsedAttr::AT_OpenCLUnrollHint:
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -1216,6 +1216,9 @@
: Sema::ConditionKind::Boolean))
return StmtError();
+ ParsedAttributesWithRange Attrs(AttrFactory);
+ MaybeParseCXX11Attributes(Attrs);
+
llvm::Optional<bool> ConstexprCondition;
if (IsConstexpr)
ConstexprCondition = Cond.getKnownValue();
@@ -1314,8 +1317,13 @@
if (ElseStmt.isInvalid())
ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
- return Actions.ActOnIfStmt(IfLoc, IsConstexpr, InitStmt.get(), Cond,
- ThenStmt.get(), ElseLoc, ElseStmt.get());
+ StmtResult Stmt = Actions.ActOnIfStmt(IfLoc, IsConstexpr, InitStmt.get(), Cond,
+ ThenStmt.get(), ElseLoc, ElseStmt.get());
+
+ if (!Attrs.empty())
+ return Actions.ProcessStmtAttributes(Stmt.get(), Attrs, Attrs.Range);
+
+ return Stmt;
}
/// ParseSwitchStatement
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -3858,6 +3858,7 @@
case ParsedAttr::AT_Deprecated:
case ParsedAttr::AT_FallThrough:
case ParsedAttr::AT_CXX11NoReturn:
+ case ParsedAttr::AT_Likely:
return true;
case ParsedAttr::AT_WarnUnusedResult:
return !ScopeName && AttrName->getName().equals("nodiscard");
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7339,6 +7339,8 @@
"use of the %0 attribute is a C++14 extension">, InGroup<CXX14>;
def ext_cxx17_attr : Extension<
"use of the %0 attribute is a C++17 extension">, InGroup<CXX17>;
+def ext_cxx2a_attr : Extension<
+ "use of the %0 attribute is a C++2a extension">, InGroup<CXX2a>;
def warn_unused_comparison : Warning<
"%select{equality|inequality|relational|three-way}0 comparison result unused">,
@@ -8158,6 +8160,9 @@
"fallthrough annotation in unreachable code">,
InGroup<ImplicitFallthrough>, DefaultIgnore;
+def err_likely_attr_invalid_placement : Error<
+ "likely annotation can't appear here">;
+
def warn_unreachable_default : Warning<
"default label in switch which covers all enumeration values">,
InGroup<CoveredSwitchDefault>, DefaultIgnore;
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -1492,6 +1492,26 @@
}];
}
+def LikelyDocs : Documentation {
+ let Category = DocCatStmt;
+ let Heading = "likely";
+ let Content = [{
+The ``likely`` (or ``clang::likely``) attribute is used to annotate that a condition is likely to be true
+this is supposed to be used as a hint by the optimizer (not yet implemented)
+
+Here is an example:
+
+.. code-block:: c++
+
+ int f(int i) {
+ if (i == 0) [[likely]]
+ return 1; //indicate that this branch is very likely to be taken
+ return 0;
+ }
+
+ }];
+}
+
def ARMInterruptDocs : Documentation {
let Category = DocCatFunction;
let Heading = "interrupt (ARM)";
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -1147,6 +1147,11 @@
let Documentation = [FallthroughDocs];
}
+def Likely : StmtAttr {
+ let Spellings = [CXX11<"", "likely", 201903>, CXX11<"clang", "likely">];
+ let Documentation = [LikelyDocs];
+}
+
def FastCall : DeclOrTypeAttr {
let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">,
Keyword<"_fastcall">];
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits