[clang] [clang] Add support for new loop attribute [[clang::code_align()]] (PR #70762)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 6 20:54:02 PST 2023
https://github.com/smanna12 updated https://github.com/llvm/llvm-project/pull/70762
>From 93d46d40f46663cfa30fc01da965887508684e25 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 30 Oct 2023 21:41:00 -0700
Subject: [PATCH 01/11] [clang] Add support for new loop attribute
[[clang::code_align()]]
---
clang/include/clang/Basic/Attr.td | 9 ++
clang/include/clang/Basic/AttrDocs.td | 43 ++++++
.../clang/Basic/DiagnosticSemaKinds.td | 4 +
clang/include/clang/Sema/Sema.h | 2 +
clang/lib/CodeGen/CGLoopInfo.cpp | 29 +++-
clang/lib/CodeGen/CGLoopInfo.h | 6 +
clang/lib/Sema/SemaStmtAttr.cpp | 53 ++++++++
clang/lib/Sema/SemaTemplateInstantiate.cpp | 8 +-
clang/test/CodeGen/code_align.c | 61 +++++++++
clang/test/Sema/code_align.c | 124 ++++++++++++++++++
clang/test/Sema/code_align_ast.c | 91 +++++++++++++
11 files changed, 426 insertions(+), 4 deletions(-)
create mode 100644 clang/test/CodeGen/code_align.c
create mode 100644 clang/test/Sema/code_align.c
create mode 100644 clang/test/Sema/code_align_ast.c
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 25231c5b82b907c..e25bea67bf9e86e 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4280,3 +4280,12 @@ def PreferredType: InheritableAttr {
let Args = [TypeArgument<"Type", 1>];
let Documentation = [PreferredTypeDocumentation];
}
+
+def CodeAlign: StmtAttr {
+ let Spellings = [CXX11<"clang", "code_align">,
+ C23<"clang", "code_align">];
+ let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
+ ErrorDiag, "'for', 'while', and 'do' statements">;
+ let Args = [ExprArgument<"NExpr">];
+ let Documentation = [CodeAlignAttrDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 05703df2129f612..5ee224e117d049c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7416,3 +7416,46 @@ that ``p->array`` must have at least ``p->count`` number of elements available:
}];
}
+
+def CodeAlignAttrDocs : Documentation {
+ let Category = DocCatVariable;
+ let Heading = "clang::code_align";
+ let Content = [{
+The ``clang::code_align(N)`` attribute applies to a loop and it specifies the
+byte alignment for a loop. The attribute accepts a positive integer constant
+initialization expression indicating the number of bytes for the minimum
+alignment boundary. Its value must be a power of 2, between 1 and 4096, such as
+1, 2, 4, 8, and so on. This attribute sets ``llvm.loop.align`` loop metadata
+when it applies on a loop statement.
+
+.. code-block:: c++
+
+ void foo() {
+ int var = 0;
+ [[clang::code_align(16)]] for (int i = 0; i < 10; ++i) var++;
+ }
+
+ void Array(int *array, size_t n) {
+ [[clang::code_align(64)]] for (int i = 0; i < n; ++i) array[i] = 0;
+ }
+
+ void count () {
+ int a1[10], int i = 0;
+ [[clang::code_align(32)]] while (i < 10) {
+ a1[i] += 3;
+ }
+
+ void check() {
+ int a = 10;
+ [[clang::code_align(8)]] do {
+ a = a + 1;
+ } while (a < 20);
+ }
+
+ template<int A>
+ void func() {
+ [[clang::code_align(A)]] for(;;) { }
+ }
+
+ }];
+}
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 224c0df7f1fb71f..4b0f24d25e3e902 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10026,6 +10026,10 @@ def err_duplicate_case_differing_expr : Error<
def warn_case_empty_range : Warning<"empty case range specified">;
def warn_missing_case_for_condition :
Warning<"no case matching constant switch condition '%0'">;
+def err_loop_attr_duplication : Error<
+ "duplicate loop attribute %0">;
+def err_attribute_argument_not_power_of_two : Error<
+ "%0 attribute argument must be a constant power of two greater than zero">;
def warn_def_missing_case : Warning<"%plural{"
"1:enumeration value %1 not explicitly handled in switch|"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1e9752345ffd173..376335e9bbe70ca 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2096,6 +2096,8 @@ class Sema final {
QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
SourceLocation AttrLoc);
+ CodeAlignAttr *BuildCodeAlignAttr(const AttributeCommonInfo &CI, Expr *E);
+
bool CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc);
bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp
index e5d9db273c2d336..a7cae301ba7bfda 100644
--- a/clang/lib/CodeGen/CGLoopInfo.cpp
+++ b/clang/lib/CodeGen/CGLoopInfo.cpp
@@ -440,6 +440,14 @@ MDNode *LoopInfo::createMetadata(
Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
}
+ // Setting clang::code_align attribute.
+ if (Attrs.CodeAlign > 0) {
+ Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.align"),
+ ConstantAsMetadata::get(ConstantInt::get(
+ llvm::Type::getInt32Ty(Ctx), Attrs.CodeAlign))};
+ LoopProperties.push_back(MDNode::get(Ctx, Vals));
+ }
+
LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
AdditionalLoopProperties.end());
return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
@@ -453,7 +461,7 @@ LoopAttributes::LoopAttributes(bool IsParallel)
VectorizeScalable(LoopAttributes::Unspecified), InterleaveCount(0),
UnrollCount(0), UnrollAndJamCount(0),
DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
- PipelineInitiationInterval(0), MustProgress(false) {}
+ PipelineInitiationInterval(0), CodeAlign(0), MustProgress(false) {}
void LoopAttributes::clear() {
IsParallel = false;
@@ -469,6 +477,7 @@ void LoopAttributes::clear() {
DistributeEnable = LoopAttributes::Unspecified;
PipelineDisabled = false;
PipelineInitiationInterval = 0;
+ CodeAlign = 0;
MustProgress = false;
}
@@ -493,8 +502,8 @@ LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
Attrs.UnrollEnable == LoopAttributes::Unspecified &&
Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
- Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
- !EndLoc && !Attrs.MustProgress)
+ Attrs.DistributeEnable == LoopAttributes::Unspecified &&
+ Attrs.CodeAlign == 0 && !StartLoc && !EndLoc && !Attrs.MustProgress)
return;
TempLoopID = MDNode::getTemporary(Header->getContext(), std::nullopt);
@@ -788,6 +797,20 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
}
}
+ // Translate 'loop attributes' arguments to equivalent Attr enums.
+ // It's being handled separately from LoopHintAttrs not to support
+ // legacy GNU attributes and pragma styles.
+ //
+ // For attribute code_align:
+ // n - 'llvm.loop.align i32 n' metadata will be emitted.
+ for (const auto *A : Attrs) {
+ if (const auto *CodeAlign = dyn_cast<CodeAlignAttr>(A)) {
+ const auto *CE = cast<ConstantExpr>(CodeAlign->getNExpr());
+ llvm::APSInt ArgVal = CE->getResultAsAPSInt();
+ setCodeAlign(ArgVal.getSExtValue());
+ }
+ }
+
setMustProgress(MustProgress);
if (CGOpts.OptimizationLevel > 0)
diff --git a/clang/lib/CodeGen/CGLoopInfo.h b/clang/lib/CodeGen/CGLoopInfo.h
index 856e892f712e31f..f5438d7865946ab 100644
--- a/clang/lib/CodeGen/CGLoopInfo.h
+++ b/clang/lib/CodeGen/CGLoopInfo.h
@@ -79,6 +79,9 @@ struct LoopAttributes {
/// Value for llvm.loop.pipeline.iicount metadata.
unsigned PipelineInitiationInterval;
+ /// Value for 'llvm.loop.align' loop metadata.
+ unsigned CodeAlign;
+
/// Value for whether the loop is required to make progress.
bool MustProgress;
};
@@ -282,6 +285,9 @@ class LoopInfoStack {
StagedAttrs.PipelineInitiationInterval = C;
}
+ /// Set the CodeAlign for the next loop pushed.
+ void setCodeAlign(unsigned C) { StagedAttrs.CodeAlign = C; }
+
/// Set no progress for the next loop pushed.
void setMustProgress(bool P) { StagedAttrs.MustProgress = P; }
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index ad20bc8871f103a..7b9dd0c97e61c1e 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -322,6 +322,56 @@ static Attr *handleUnlikely(Sema &S, Stmt *St, const ParsedAttr &A,
return ::new (S.Context) UnlikelyAttr(S.Context, A);
}
+CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
+ Expr *E) {
+ if (!E->isValueDependent()) {
+ llvm::APSInt ArgVal;
+ ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
+ if (Res.isInvalid())
+ return nullptr;
+ E = Res.get();
+
+ // This attribute requires a strictly positive value.
+ if (ArgVal <= 0) {
+ Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
+ << CI << /*positive*/ 0;
+ return nullptr;
+ }
+
+ // This attribute requires a single constant power of two greater than zero.
+ if (!ArgVal.isPowerOf2()) {
+ Diag(E->getExprLoc(), diag::err_attribute_argument_not_power_of_two)
+ << CI;
+ return nullptr;
+ }
+ }
+
+ return new (Context) CodeAlignAttr(Context, CI, E);
+}
+
+static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
+
+ Expr *E = A.getArgAsExpr(0);
+ return S.BuildCodeAlignAttr(A, E);
+}
+
+// Emit duplicate error for [[clang::code_align()]] attribute.
+template <typename LoopAttrT>
+static void
+CheckForDuplicateLoopAttribute(Sema &S,
+ const SmallVectorImpl<const Attr *> &Attrs) {
+ const LoopAttrT *LoopAttr = nullptr;
+
+ for (const auto *I : Attrs) {
+ if (LoopAttr && isa<LoopAttrT>(I)) {
+ // Cannot specify same type of attribute twice.
+ S.Diag(I->getLocation(), diag::err_loop_attr_duplication) << LoopAttr;
+ }
+ if (isa<LoopAttrT>(I))
+ LoopAttr = cast<LoopAttrT>(I);
+ }
+}
+
#define WANT_STMT_MERGE_LOGIC
#include "clang/Sema/AttrParsedAttrImpl.inc"
#undef WANT_STMT_MERGE_LOGIC
@@ -523,6 +573,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
return handleLikely(S, St, A, Range);
case ParsedAttr::AT_Unlikely:
return handleUnlikely(S, St, A, Range);
+ case ParsedAttr::AT_CodeAlign:
+ return handleCodeAlignAttr(S, St, A);
default:
// N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a
// declaration attribute is not written on a statement, but this code is
@@ -541,4 +593,5 @@ void Sema::ProcessStmtAttributes(Stmt *S, const ParsedAttributes &InAttrs,
}
CheckForIncompatibleAttributes(*this, OutAttrs);
+ CheckForDuplicateLoopAttribute<CodeAlignAttr>(*this, OutAttrs);
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index e09897318ba9883..436364cfc0a4dce 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1374,7 +1374,7 @@ namespace {
const AlwaysInlineAttr *
TransformStmtAlwaysInlineAttr(const Stmt *OrigS, const Stmt *InstS,
const AlwaysInlineAttr *A);
-
+ const CodeAlignAttr *TransformCodeAlignAttr(const CodeAlignAttr *CA);
ExprResult TransformPredefinedExpr(PredefinedExpr *E);
ExprResult TransformDeclRefExpr(DeclRefExpr *E);
ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
@@ -1905,6 +1905,12 @@ const AlwaysInlineAttr *TemplateInstantiator::TransformStmtAlwaysInlineAttr(
return A;
}
+const CodeAlignAttr *
+TemplateInstantiator::TransformCodeAlignAttr(const CodeAlignAttr *CA) {
+ Expr *TransformedExpr = getDerived().TransformExpr(CA->getNExpr()).get();
+ return getSema().BuildCodeAlignAttr(*CA, TransformedExpr);
+}
+
ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
Decl *AssociatedDecl, const NonTypeTemplateParmDecl *parm,
SourceLocation loc, TemplateArgument arg,
diff --git a/clang/test/CodeGen/code_align.c b/clang/test/CodeGen/code_align.c
new file mode 100644
index 000000000000000..f1ee06ff70eef27
--- /dev/null
+++ b/clang/test/CodeGen/code_align.c
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-C %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -fsyntax-only -emit-llvm %s -o - | FileCheck %s --check-prefixes CHECK-C,CHECK-CPP
+
+// Add CodeGen tests for Loop attribute: [[clang::code_align)]].
+
+// CHECK-C: br label %for.cond, !llvm.loop ![[MD_FP:[0-9]+]]
+// CHECK-C: br label %while.cond, !llvm.loop ![[MD_FP_1:[0-9]+]]
+// CHECK-C: br i1 %cmp3, label %do.body, label %do.end, !llvm.loop ![[MD_FP_2:[0-9]+]]
+// CHECK-C: br label %for.cond5, !llvm.loop ![[MD_FP_3:[0-9]+]]
+
+// CHECK-CPP: br label %for.cond, !llvm.loop ![[MD_FP_4:[0-9]+]]
+// CHECK-CPP: br label %for.cond2, !llvm.loop ![[MD_FP_5:[0-9]+]]
+
+void bar(int);
+void code_align() {
+ int a[10];
+ // CHECK-C: ![[MD_FP]] = distinct !{![[MD_FP]], ![[MP:[0-9]+]], ![[MD_code_align:[0-9]+]]}
+ // CHECK-C-NEXT: ![[MP]] = !{!"llvm.loop.mustprogress"}
+ // CHECK-C-NEXT: ![[MD_code_align]] = !{!"llvm.loop.align", i32 4}
+ [[clang::code_align(4)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
+ // CHECK-C: ![[MD_FP_1]] = distinct !{![[MD_FP_1]], ![[MP]], ![[MD_code_align_1:[0-9]+]]}
+ // CHECK-C-NEXT: ![[MD_code_align_1]] = !{!"llvm.loop.align", i32 16}
+ int i = 0;
+ [[clang::code_align(16)]] while (i < 60) {
+ a[i] += 3;
+ }
+
+ // CHECK-C: ![[MD_FP_2]] = distinct !{![[MD_FP_2]], ![[MP]], ![[MD_code_align_2:[0-9]+]]}
+ // CHECK-C-NEXT: ![[MD_code_align_2]] = !{!"llvm.loop.align", i32 8}
+ int b = 10;
+ [[clang::code_align(8)]] do {
+ b = b + 1;
+ } while (b < 20);
+
+ // CHECK-C: ![[MD_FP_3]] = distinct !{![[MD_FP_3]], ![[MP]], ![[MD_code_align_3:[0-9]+]]}
+ // CHECK-C-NEXT: ![[MD_code_align_3]] = !{!"llvm.loop.align", i32 64}
+ [[clang::code_align(64)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+}
+
+#if __cplusplus >= 201103L
+template <int A, int B>
+void code_align_cpp() {
+ int a[10];
+ // CHECK-CPP: ![[MD_FP_4]] = distinct !{![[MD_FP_4]], ![[MP]], ![[MD_code_align_4:[0-9]+]]}
+ // CHECK-CPP-NEXT: ![[MD_code_align_4]] = !{!"llvm.loop.align", i32 32}
+ [[clang::code_align(A)]] for (int i = 0; i != 10; ++i)
+ a[i] = 0;
+
+ // CHECK-CPP: ![[MD_FP_5]] = distinct !{![[MD_FP_5]], ![[MD_code_align]]}
+ int c[] = {0, 1, 2, 3, 4, 5};
+ [[clang::code_align(B)]] for (int n : c) { n *= 2; }
+}
+
+int main() {
+ code_align_cpp<32, 4>();
+ return 0;
+}
+#endif
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
new file mode 100644
index 000000000000000..74f39ffe23300d0
--- /dev/null
+++ b/clang/test/Sema/code_align.c
@@ -0,0 +1,124 @@
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,c-local %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cpp-local -pedantic -x c++ -std=c++11 %s
+
+// Add diagnostics tests for Loop attribute: [[clang::code_align()]].
+
+void foo() {
+ int i;
+ int a[10], b[10];
+
+ [[clang::code_align(8)]]
+ for (i = 0; i < 10; ++i) { // this is OK
+ a[i] = b[i] = 0;
+ }
+ // expected-error at +1 {{'code_align' attribute only applies to 'for', 'while', and 'do' statements}}
+ [[clang::code_align(4)]]
+ i = 7;
+ for (i = 0; i < 10; ++i) {
+ a[i] = b[i] = 0;
+ }
+
+ // expected-error at +1{{'code_align' attribute cannot be applied to a declaration}}
+ [[clang::code_align(12)]] int n[10];
+}
+
+void bar(int);
+#if __cplusplus >= 201103L
+// cpp-local-note at +2 {{declared here}}
+#endif
+void foo1(int A)
+{
+ // expected-error at +1 {{'code_align' attribute requires a positive integral compile time constant expression}}
+ [[clang::code_align(0)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
+ // expected-error at +1{{'code_align' attribute requires a positive integral compile time constant expression}}
+ [[clang::code_align(-4)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
+#if __cplusplus >= 201103L
+ // cpp-local-error at +4 {{integral constant expression must have integral or unscoped enumeration type, not 'double'}}
+#else
+ // c-local-error at +2 {{integer constant expression must have integer type, not 'double'}}
+#endif
+ [[clang::code_align(64.0)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
+ // expected-error at +1 {{'code_align' attribute takes one argument}}
+ [[clang::code_align()]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
+ // expected-error at +1 {{'code_align' attribute takes one argument}}
+ [[clang::code_align(4,8)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
+ // no diagnostic is expected
+ [[clang::code_align(32)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
+#if __cplusplus >= 201103L
+ // cpp-local-error at +4 {{integral constant expression must have integral or unscoped enumeration type, not 'const char[4]'}}
+#else
+ // c-local-error at +2 {{integer constant expression must have integer type, not 'char[4]'}}
+#endif
+ [[clang::code_align("abc")]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
+ [[clang::code_align(64)]]
+ // expected-error at +1 {{duplicate loop attribute 'code_align'}}
+ [[clang::code_align(64)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
+ // expected-error at +1 {{'code_align' attribute argument must be a constant power of two greater than zero}}
+ [[clang::code_align(7)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
+#if __cplusplus >= 201103L
+ // cpp-local-error at +5 {{expression is not an integral constant expression}}
+ // cpp-local-note at +4 {{function parameter 'A' with unknown value cannot be used in a constant expression}}
+#else
+ // c-local-error at +2 {{expression is not an integer constant expression}}
+#endif
+ [[clang::code_align(A)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+}
+
+#if __cplusplus >= 201103L
+void check_code_align_expression() {
+ int a[10];
+
+ // Test that checks expression is not a constant expression.
+ int foo2; // cpp-local-note {{declared here}}
+ // cpp-local-error at +2{{expression is not an integral constant expression}}
+ // cpp-local-note at +1{{read of non-const variable 'foo2' is not allowed in a constant expression}}
+ [[clang::code_align(foo2 + 1)]]
+ for (int i = 0; i != 10; ++i)
+ a[i] = 0;
+
+ // Test that checks expression is a constant expression.
+ constexpr int bars = 0;
+ [[clang::code_align(bars + 1)]]
+ for (int i = 0; i != 10; ++i)
+ a[i] = 0;
+}
+
+template <int A, int B, int C, int D>
+void code_align_dependent() {
+ [[clang::code_align(C)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
+ [[clang::code_align(A)]]
+ // cpp-local-error at +1 {{duplicate loop attribute 'code_align'}}
+ [[clang::code_align(B)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
+ // cpp-local-error at +1{{'code_align' attribute requires a positive integral compile time constant expression}}
+ [[clang::code_align(D)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+}
+
+int main() {
+ code_align_dependent<8, 16, 32, -10>(); // cpp-local-note{{in instantiation of function template specialization 'code_align_dependent<8, 16, 32, -10>' requested here}}
+ return 0;
+}
+#endif
diff --git a/clang/test/Sema/code_align_ast.c b/clang/test/Sema/code_align_ast.c
new file mode 100644
index 000000000000000..300e55d696fd402
--- /dev/null
+++ b/clang/test/Sema/code_align_ast.c
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -fsyntax-only -ast-dump -verify %s | FileCheck -check-prefix=CHECK-C %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -fsyntax-only -ast-dump %s | FileCheck %s --check-prefixes CHECK-C,CHECK-CPP
+
+// expected-no-diagnostics
+
+// Add AST tests for Loop attribute: [[clang::code_align()]].
+
+void bar(int);
+// CHECK-C: FunctionDecl{{.*}}code_align 'void ()'
+void code_align() {
+ int a1[10], a2[10];
+ // CHECK-C: AttributedStmt
+ // CHECK-C-NEXT: CodeAlignAttr
+ // CHECK-C-NEXT: ConstantExpr{{.*}}'int'
+ // CHECK-C-NEXT: value: Int 16
+ // CHECK-C-NEXT: IntegerLiteral{{.*}}16{{$}}
+ [[clang::code_align(16)]] for (int p = 0; p < 128; ++p) {
+ a1[p] = a2[p] = 0;
+ }
+
+ // CHECK-C: AttributedStmt
+ // CHECK-C-NEXT: CodeAlignAttr
+ // CHECK-C-NEXT: ConstantExpr{{.*}}'int'
+ // CHECK-C-NEXT: value: Int 4
+ // CHECK-C-NEXT: IntegerLiteral{{.*}}4{{$}}
+ int i = 0;
+ [[clang::code_align(4)]] while (i < 30) {
+ a1[i] += 3;
+ }
+
+ // CHECK-C: AttributedStmt
+ // CHECK-C-NEXT: CodeAlignAttr
+ // CHECK-C-NEXT: ConstantExpr{{.*}}'int'
+ // CHECK-C-NEXT: value: Int 32
+ // CHECK-C-NEXT: IntegerLiteral{{.*}}32{{$}}
+ for (int i = 0; i < 128; ++i) {
+ [[clang::code_align(32)]] for (int j = 0; j < 128; ++j) {
+ a1[i] += a1[j];
+ }
+ }
+
+ // CHECK-C: AttributedStmt
+ // CHECK-C-NEXT: CodeAlignAttr
+ // CHECK-C-NEXT: ConstantExpr{{.*}}'int'
+ // CHECK-C-NEXT: value: Int 64
+ // CHECK-C-NEXT: IntegerLiteral{{.*}}64{{$}}
+ [[clang::code_align(64)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
+ // CHECK-C: AttributedStmt
+ // CHECK-C-NEXT: CodeAlignAttr
+ // CHECK-C-NEXT: ConstantExpr{{.*}}'int'
+ // CHECK-C-NEXT: value: Int 4
+ // CHECK-C-NEXT: IntegerLiteral{{.*}}4{{$}}
+ int b = 10;
+ [[clang::code_align(4)]] do {
+ b = b + 1;
+ } while (b < 20);
+}
+
+#if __cplusplus >= 201103L
+//CHECK-CPP: FunctionDecl{{.*}}used code_align_cpp 'void ()' implicit_instantiation
+template <int A, int B>
+void code_align_cpp() {
+ int a[10];
+ // CHECK-CPP: AttributedStmt
+ // CHECK-CPP-NEXT: CodeAlignAttr
+ // CHECK-CPP-NEXT: ConstantExpr{{.*}}'int'
+ // CHECK-CPP-NEXT: value: Int 32
+ // CHECK-CPP-NEXT: SubstNonTypeTemplateParmExpr{{.*}}'int'
+ // CHECK-CPP-NEXT: NonTypeTemplateParmDecl{{.*}}referenced 'int' depth 0 index 0 A
+ // CHECK-CPP-NEXT: IntegerLiteral{{.*}}32{{$}}
+ [[clang::code_align(A)]] for (int i = 0; i != 10; ++i)
+ a[i] = 0;
+
+ // CHECK-CPP: AttributedStmt
+ // CHECK-CPP-NEXT: CodeAlignAttr
+ // CHECK-CPP-NEXT: ConstantExpr{{.*}}'int'
+ // CHECK-CPP-NEXT: value: Int 4
+ // CHECK-CPP-NEXT: SubstNonTypeTemplateParmExpr{{.*}}'int'
+ // CHECK-CPP-NEXT: NonTypeTemplateParmDecl{{.*}}referenced 'int' depth 0 index 1 B
+ // CHECK-CPP-NEXT: IntegerLiteral{{.*}}4{{$}}
+ int c[] = {0, 1, 2, 3, 4, 5};
+ [[clang::code_align(B)]] for (int n : c) { n *= 2; }
+}
+
+int main() {
+ code_align_cpp<32, 4>();
+ return 0;
+}
+#endif
>From d049dc9997bdb78ff7e7cbf9b04aa42b9274cfd9 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Wed, 1 Nov 2023 20:24:51 -0700
Subject: [PATCH 02/11] Address review comments
---
clang/include/clang/Basic/Attr.td | 13 ++++++--
clang/include/clang/Basic/AttrDocs.td | 9 +++---
.../clang/Basic/DiagnosticSemaKinds.td | 4 +--
clang/lib/CodeGen/CGLoopInfo.cpp | 7 ++--
clang/lib/CodeGen/CGLoopInfo.h | 4 +--
clang/lib/Sema/SemaStmtAttr.cpp | 32 ++++++++-----------
clang/lib/Sema/SemaTemplateInstantiate.cpp | 2 +-
clang/test/CodeGen/code_align.c | 6 ++--
clang/test/Sema/code_align.c | 21 ++++++------
clang/test/Sema/code_align_ast.c | 8 ++---
10 files changed, 51 insertions(+), 55 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index e25bea67bf9e86e..88d232f4aba0163 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4282,10 +4282,17 @@ def PreferredType: InheritableAttr {
}
def CodeAlign: StmtAttr {
- let Spellings = [CXX11<"clang", "code_align">,
- C23<"clang", "code_align">];
+ let Spellings = [Clang<"code_align">];
let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
ErrorDiag, "'for', 'while', and 'do' statements">;
- let Args = [ExprArgument<"NExpr">];
+ let Args = [ExprArgument<"Alignment">];
let Documentation = [CodeAlignAttrDocs];
+ let AdditionalMembers = [{
+ static int getMinValue() {
+ return 1;
+ }
+ static int getMaxValue() {
+ return 4096;
+ }
+ }];
}
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 5ee224e117d049c..099c7dc547cfa81 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7421,12 +7421,11 @@ def CodeAlignAttrDocs : Documentation {
let Category = DocCatVariable;
let Heading = "clang::code_align";
let Content = [{
-The ``clang::code_align(N)`` attribute applies to a loop and it specifies the
-byte alignment for a loop. The attribute accepts a positive integer constant
+The ``clang::code_align(N)`` attribute applies to a loop and specifies the byte
+alignment for a loop. The attribute accepts a positive integer constant
initialization expression indicating the number of bytes for the minimum
-alignment boundary. Its value must be a power of 2, between 1 and 4096, such as
-1, 2, 4, 8, and so on. This attribute sets ``llvm.loop.align`` loop metadata
-when it applies on a loop statement.
+alignment boundary. Its value must be a power of 2, between 1 and 4096
+(inclusive).
.. code-block:: c++
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4b0f24d25e3e902..5d9aaba57131445 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10028,8 +10028,8 @@ def warn_missing_case_for_condition :
Warning<"no case matching constant switch condition '%0'">;
def err_loop_attr_duplication : Error<
"duplicate loop attribute %0">;
-def err_attribute_argument_not_power_of_two : Error<
- "%0 attribute argument must be a constant power of two greater than zero">;
+def err_attribute_power_of_two_in_range : Error<
+ "%0 attribute must be a constant power of two between %1 and %2 inclusive">;
def warn_def_missing_case : Warning<"%plural{"
"1:enumeration value %1 not explicitly handled in switch|"
diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp
index a7cae301ba7bfda..a951198b925a513 100644
--- a/clang/lib/CodeGen/CGLoopInfo.cpp
+++ b/clang/lib/CodeGen/CGLoopInfo.cpp
@@ -797,15 +797,12 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
}
}
- // Translate 'loop attributes' arguments to equivalent Attr enums.
- // It's being handled separately from LoopHintAttrs not to support
- // legacy GNU attributes and pragma styles.
- //
+ // Identify loop attribute 'code_align' from Attrs.
// For attribute code_align:
// n - 'llvm.loop.align i32 n' metadata will be emitted.
for (const auto *A : Attrs) {
if (const auto *CodeAlign = dyn_cast<CodeAlignAttr>(A)) {
- const auto *CE = cast<ConstantExpr>(CodeAlign->getNExpr());
+ const auto *CE = cast<ConstantExpr>(CodeAlign->getAlignment());
llvm::APSInt ArgVal = CE->getResultAsAPSInt();
setCodeAlign(ArgVal.getSExtValue());
}
diff --git a/clang/lib/CodeGen/CGLoopInfo.h b/clang/lib/CodeGen/CGLoopInfo.h
index f5438d7865946ab..a1c8c7e5307fd9c 100644
--- a/clang/lib/CodeGen/CGLoopInfo.h
+++ b/clang/lib/CodeGen/CGLoopInfo.h
@@ -79,7 +79,7 @@ struct LoopAttributes {
/// Value for llvm.loop.pipeline.iicount metadata.
unsigned PipelineInitiationInterval;
- /// Value for 'llvm.loop.align' loop metadata.
+ /// Value for 'llvm.loop.align' metadata.
unsigned CodeAlign;
/// Value for whether the loop is required to make progress.
@@ -285,7 +285,7 @@ class LoopInfoStack {
StagedAttrs.PipelineInitiationInterval = C;
}
- /// Set the CodeAlign for the next loop pushed.
+ /// Set value of code align for the next loop pushed.
void setCodeAlign(unsigned C) { StagedAttrs.CodeAlign = C; }
/// Set no progress for the next loop pushed.
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 7b9dd0c97e61c1e..c34fc4de5b0c670 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -331,17 +331,13 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
return nullptr;
E = Res.get();
- // This attribute requires a strictly positive value.
- if (ArgVal <= 0) {
- Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
- << CI << /*positive*/ 0;
- return nullptr;
- }
-
- // This attribute requires a single constant power of two greater than zero.
- if (!ArgVal.isPowerOf2()) {
- Diag(E->getExprLoc(), diag::err_attribute_argument_not_power_of_two)
- << CI;
+ int align_value = ArgVal.getSExtValue();
+ if (align_value < CodeAlignAttr::getMinValue() ||
+ align_value > CodeAlignAttr::getMaxValue() ||
+ !ArgVal.isPowerOf2()) {
+ Diag(CI.getLoc(), diag:: err_attribute_power_of_two_in_range)
+ << CI << CodeAlignAttr::getMinValue()
+ << CodeAlignAttr::getMaxValue();
return nullptr;
}
}
@@ -360,15 +356,15 @@ template <typename LoopAttrT>
static void
CheckForDuplicateLoopAttribute(Sema &S,
const SmallVectorImpl<const Attr *> &Attrs) {
- const LoopAttrT *LoopAttr = nullptr;
-
+ const Attr *A = nullptr;
for (const auto *I : Attrs) {
- if (LoopAttr && isa<LoopAttrT>(I)) {
- // Cannot specify same type of attribute twice.
- S.Diag(I->getLocation(), diag::err_loop_attr_duplication) << LoopAttr;
+ if (isa<LoopAttrT>(I)) {
+ if (A) {
+ // Cannot specify same type of attribute twice.
+ S.Diag(I->getLocation(), diag::err_loop_attr_duplication) << A;
+ }
+ A = I;
}
- if (isa<LoopAttrT>(I))
- LoopAttr = cast<LoopAttrT>(I);
}
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 436364cfc0a4dce..cd679d9a1f83529 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1907,7 +1907,7 @@ const AlwaysInlineAttr *TemplateInstantiator::TransformStmtAlwaysInlineAttr(
const CodeAlignAttr *
TemplateInstantiator::TransformCodeAlignAttr(const CodeAlignAttr *CA) {
- Expr *TransformedExpr = getDerived().TransformExpr(CA->getNExpr()).get();
+ Expr *TransformedExpr = getDerived().TransformExpr(CA->getAlignment()).get();
return getSema().BuildCodeAlignAttr(*CA, TransformedExpr);
}
diff --git a/clang/test/CodeGen/code_align.c b/clang/test/CodeGen/code_align.c
index f1ee06ff70eef27..f6d86ec969ae5f6 100644
--- a/clang/test/CodeGen/code_align.c
+++ b/clang/test/CodeGen/code_align.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-C %s
-// RUN: %clang_cc1 -x c++ -std=c++11 -fsyntax-only -emit-llvm %s -o - | FileCheck %s --check-prefixes CHECK-C,CHECK-CPP
-
-// Add CodeGen tests for Loop attribute: [[clang::code_align)]].
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -x c %s %s -o - | FileCheck -check-prefix=CHECK-C %s
+// RUN: %clang_cc1 -fsyntax-only -emit-llvm -x c++ -std=c++11 %s -o - | FileCheck %s --check-prefixes CHECK-C,CHECK-CPP
// CHECK-C: br label %for.cond, !llvm.loop ![[MD_FP:[0-9]+]]
// CHECK-C: br label %while.cond, !llvm.loop ![[MD_FP_1:[0-9]+]]
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index 74f39ffe23300d0..f4f977dbf65767d 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,c-local %s
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cpp-local -pedantic -x c++ -std=c++11 %s
-
-// Add diagnostics tests for Loop attribute: [[clang::code_align()]].
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,c-local -x c %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cpp-local -pedantic -x c++ -std=c++11 %s
void foo() {
int i;
@@ -28,11 +26,11 @@ void bar(int);
#endif
void foo1(int A)
{
- // expected-error at +1 {{'code_align' attribute requires a positive integral compile time constant expression}}
+ // expected-error at +1 {{'code_align' attribute must be a constant power of two between 1 and 4096 inclusive}}
[[clang::code_align(0)]]
for(int I=0; I<128; ++I) { bar(I); }
- // expected-error at +1{{'code_align' attribute requires a positive integral compile time constant expression}}
+ // expected-error at +1{{'code_align' attribute must be a constant power of two between 1 and 4096 inclusive}}
[[clang::code_align(-4)]]
for(int I=0; I<128; ++I) { bar(I); }
@@ -69,10 +67,14 @@ void foo1(int A)
[[clang::code_align(64)]]
for(int I=0; I<128; ++I) { bar(I); }
- // expected-error at +1 {{'code_align' attribute argument must be a constant power of two greater than zero}}
+ // expected-error at +1 {{'code_align' attribute must be a constant power of two between 1 and 4096 inclusive}}
[[clang::code_align(7)]]
for(int I=0; I<128; ++I) { bar(I); }
+ // expected-error at +1 {{'code_align' attribute must be a constant power of two between 1 and 4096 inclusive}}
+ [[clang::code_align(5000)]]
+ for(int I=0; I<128; ++I) { bar(I); }
+
#if __cplusplus >= 201103L
// cpp-local-error at +5 {{expression is not an integral constant expression}}
// cpp-local-note at +4 {{function parameter 'A' with unknown value cannot be used in a constant expression}}
@@ -112,13 +114,14 @@ void code_align_dependent() {
[[clang::code_align(B)]]
for(int I=0; I<128; ++I) { bar(I); }
- // cpp-local-error at +1{{'code_align' attribute requires a positive integral compile time constant expression}}
+ // cpp-local-error at +2{{'code_align' attribute must be a constant power of two between 1 and 4096 inclusive}}
+ // cpp-local-note@#neg-instantiation {{in instantiation of function template specialization}}
[[clang::code_align(D)]]
for(int I=0; I<128; ++I) { bar(I); }
}
int main() {
- code_align_dependent<8, 16, 32, -10>(); // cpp-local-note{{in instantiation of function template specialization 'code_align_dependent<8, 16, 32, -10>' requested here}}
+ code_align_dependent<8, 16, 32, -10>(); // #neg-instantiation
return 0;
}
#endif
diff --git a/clang/test/Sema/code_align_ast.c b/clang/test/Sema/code_align_ast.c
index 300e55d696fd402..962cfa09c539216 100644
--- a/clang/test/Sema/code_align_ast.c
+++ b/clang/test/Sema/code_align_ast.c
@@ -1,9 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -ast-dump -verify %s | FileCheck -check-prefix=CHECK-C %s
-// RUN: %clang_cc1 -x c++ -std=c++11 -fsyntax-only -ast-dump %s | FileCheck %s --check-prefixes CHECK-C,CHECK-CPP
-
-// expected-no-diagnostics
-
-// Add AST tests for Loop attribute: [[clang::code_align()]].
+// RUN: %clang_cc1 -fsyntax-only -ast-dump -verify -x c %s | FileCheck -check-prefix=CHECK-C %s
+// RUN: %clang_cc1 -fsyntax-only -ast-dump -x c++ -std=c++11 %s | FileCheck %s --check-prefixes CHECK-C,CHECK-CPP
void bar(int);
// CHECK-C: FunctionDecl{{.*}}code_align 'void ()'
>From 6c44cc15df0b98967b6a76c73a16a77539c47ccc Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Wed, 1 Nov 2023 20:41:41 -0700
Subject: [PATCH 03/11] Fix clang format errors
---
clang/lib/Sema/SemaStmtAttr.cpp | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index c34fc4de5b0c670..8a75b3021223083 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -333,11 +333,9 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
int align_value = ArgVal.getSExtValue();
if (align_value < CodeAlignAttr::getMinValue() ||
- align_value > CodeAlignAttr::getMaxValue() ||
- !ArgVal.isPowerOf2()) {
- Diag(CI.getLoc(), diag:: err_attribute_power_of_two_in_range)
- << CI << CodeAlignAttr::getMinValue()
- << CodeAlignAttr::getMaxValue();
+ align_value > CodeAlignAttr::getMaxValue() || !ArgVal.isPowerOf2()) {
+ Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
+ << CI << CodeAlignAttr::getMinValue() << CodeAlignAttr::getMaxValue();
return nullptr;
}
}
@@ -362,8 +360,8 @@ CheckForDuplicateLoopAttribute(Sema &S,
if (A) {
// Cannot specify same type of attribute twice.
S.Diag(I->getLocation(), diag::err_loop_attr_duplication) << A;
- }
- A = I;
+ }
+ A = I;
}
}
}
>From f35c4be758851246b8d11fe7cf64d760e6531a11 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Thu, 2 Nov 2023 06:14:58 -0700
Subject: [PATCH 04/11] Fix Lit test failure
---
clang/test/Sema/code_align_ast.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/test/Sema/code_align_ast.c b/clang/test/Sema/code_align_ast.c
index 962cfa09c539216..2cfbf11f1fd0eab 100644
--- a/clang/test/Sema/code_align_ast.c
+++ b/clang/test/Sema/code_align_ast.c
@@ -1,6 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -ast-dump -verify -x c %s | FileCheck -check-prefix=CHECK-C %s
// RUN: %clang_cc1 -fsyntax-only -ast-dump -x c++ -std=c++11 %s | FileCheck %s --check-prefixes CHECK-C,CHECK-CPP
+// expected-no-diagnostics
+
void bar(int);
// CHECK-C: FunctionDecl{{.*}}code_align 'void ()'
void code_align() {
>From 4c40ce27e81ae40f05aeabb513881032c04feb92 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 6 Nov 2023 09:30:22 -0800
Subject: [PATCH 05/11] Address review comments
---
clang/docs/ReleaseNotes.rst | 17 +++++++
.../clang/Basic/DiagnosticSemaKinds.td | 3 +-
clang/lib/Sema/SemaStmtAttr.cpp | 28 ++++++----
clang/test/Sema/code_align.c | 51 ++++++++-----------
4 files changed, 57 insertions(+), 42 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bc28bb567f6932a..37e985cb13d5072 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -288,6 +288,23 @@ Attribute Changes in Clang
When viewing ``S::FruitKind`` in a debugger, it will behave as if the member
was declared as type ``E`` rather than ``unsigned``.
+- Clang now supports ``[[clang::code_align(N)]]`` as an attribute which can be
+ applied to a loop and specifies the byte alignment for a loop. This attribute
+ accepts a positive integer constant initialization expression indicating the
+ number of bytes for the minimum alignment boundary. Its value must be a power
+ of 2, between 1 and 4096(inclusive).
+
+ .. code-block:: c++
+
+ void Array(int *array, size_t n) {
+ [[clang::code_align(64)]] for (int i = 0; i < n; ++i) array[i] = 0;
+ }
+
+ template<int A>
+ void func() {
+ [[clang::code_align(A)]] for(;;) { }
+ }
+
Improvements to Clang's diagnostics
-----------------------------------
- Clang constexpr evaluator now prints template arguments when displaying
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5d9aaba57131445..8dab0bb996d0e9d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10029,7 +10029,8 @@ def warn_missing_case_for_condition :
def err_loop_attr_duplication : Error<
"duplicate loop attribute %0">;
def err_attribute_power_of_two_in_range : Error<
- "%0 attribute must be a constant power of two between %1 and %2 inclusive">;
+ "%0 attribute requires an integer argument which is a constant power of two "
+ "between %1 and %2 inclusive - got %3">;
def warn_def_missing_case : Warning<"%plural{"
"1:enumeration value %1 not explicitly handled in switch|"
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 8a75b3021223083..a75b1d0b085bb34 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -331,15 +331,23 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
return nullptr;
E = Res.get();
- int align_value = ArgVal.getSExtValue();
- if (align_value < CodeAlignAttr::getMinValue() ||
- align_value > CodeAlignAttr::getMaxValue() || !ArgVal.isPowerOf2()) {
+ // This attribute requires a strictly positive value.
+ if (ArgVal <= 0) {
+ Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
+ << CI << /*positive*/ 0;
+ return nullptr;
+ }
+
+ // This attribute requires an integer argument which is a constant power of
+ // two between 1 and 4096 inclusive.
+ int AlignValue = ArgVal.getSExtValue();
+ if (AlignValue > CodeAlignAttr::getMaxValue() || !ArgVal.isPowerOf2()) {
Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
- << CI << CodeAlignAttr::getMinValue() << CodeAlignAttr::getMaxValue();
+ << CI << CodeAlignAttr::getMinValue() << CodeAlignAttr::getMaxValue()
+ << AlignValue;
return nullptr;
}
}
-
return new (Context) CodeAlignAttr(Context, CI, E);
}
@@ -350,16 +358,16 @@ static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
}
// Emit duplicate error for [[clang::code_align()]] attribute.
-template <typename LoopAttrT>
static void
-CheckForDuplicateLoopAttribute(Sema &S,
- const SmallVectorImpl<const Attr *> &Attrs) {
+CheckForDuplicateCodeAlignAttribute(Sema &S,
+ const SmallVectorImpl<const Attr *> &Attrs) {
const Attr *A = nullptr;
for (const auto *I : Attrs) {
- if (isa<LoopAttrT>(I)) {
+ if (isa<CodeAlignAttr>(I)) {
if (A) {
// Cannot specify same type of attribute twice.
S.Diag(I->getLocation(), diag::err_loop_attr_duplication) << A;
+ S.Diag(A->getLocation(),diag::note_previous_attribute);
}
A = I;
}
@@ -587,5 +595,5 @@ void Sema::ProcessStmtAttributes(Stmt *S, const ParsedAttributes &InAttrs,
}
CheckForIncompatibleAttributes(*this, OutAttrs);
- CheckForDuplicateLoopAttribute<CodeAlignAttr>(*this, OutAttrs);
+ CheckForDuplicateCodeAlignAttribute(*this, OutAttrs);
}
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index f4f977dbf65767d..715d2896969464b 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -21,24 +21,19 @@ void foo() {
}
void bar(int);
-#if __cplusplus >= 201103L
-// cpp-local-note at +2 {{declared here}}
-#endif
+// cpp-local-note at +1 {{declared here}}
void foo1(int A)
{
- // expected-error at +1 {{'code_align' attribute must be a constant power of two between 1 and 4096 inclusive}}
+ // expected-error at +1 {{'code_align' attribute requires a positive integral compile time constant expression}}
[[clang::code_align(0)]]
for(int I=0; I<128; ++I) { bar(I); }
- // expected-error at +1{{'code_align' attribute must be a constant power of two between 1 and 4096 inclusive}}
+ // expected-error at +1 {{'code_align' attribute requires a positive integral compile time constant expression}}
[[clang::code_align(-4)]]
for(int I=0; I<128; ++I) { bar(I); }
-#if __cplusplus >= 201103L
- // cpp-local-error at +4 {{integral constant expression must have integral or unscoped enumeration type, not 'double'}}
-#else
- // c-local-error at +2 {{integer constant expression must have integer type, not 'double'}}
-#endif
+ // cpp-local-error at +2 {{integral constant expression must have integral or unscoped enumeration type, not 'double'}}
+ // c-local-error at +1 {{integer constant expression must have integer type, not 'double'}}
[[clang::code_align(64.0)]]
for(int I=0; I<128; ++I) { bar(I); }
@@ -54,38 +49,30 @@ void foo1(int A)
[[clang::code_align(32)]]
for(int I=0; I<128; ++I) { bar(I); }
-#if __cplusplus >= 201103L
- // cpp-local-error at +4 {{integral constant expression must have integral or unscoped enumeration type, not 'const char[4]'}}
-#else
- // c-local-error at +2 {{integer constant expression must have integer type, not 'char[4]'}}
-#endif
+ // cpp-local-error at +2 {{integral constant expression must have integral or unscoped enumeration type, not 'const char[4]'}}
+ // c-local-error at +1 {{integer constant expression must have integer type, not 'char[4]'}}
[[clang::code_align("abc")]]
for(int I=0; I<128; ++I) { bar(I); }
- [[clang::code_align(64)]]
- // expected-error at +1 {{duplicate loop attribute 'code_align'}}
- [[clang::code_align(64)]]
+ [[clang::code_align(64)]] // expected-note {{previous attribute is here}}
+ [[clang::code_align(64)]] // expected-error {{duplicate loop attribute 'code_align'}}
for(int I=0; I<128; ++I) { bar(I); }
- // expected-error at +1 {{'code_align' attribute must be a constant power of two between 1 and 4096 inclusive}}
+ // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive - got 7}}
[[clang::code_align(7)]]
for(int I=0; I<128; ++I) { bar(I); }
- // expected-error at +1 {{'code_align' attribute must be a constant power of two between 1 and 4096 inclusive}}
+ // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive - got 5000}}
[[clang::code_align(5000)]]
for(int I=0; I<128; ++I) { bar(I); }
-#if __cplusplus >= 201103L
- // cpp-local-error at +5 {{expression is not an integral constant expression}}
- // cpp-local-note at +4 {{function parameter 'A' with unknown value cannot be used in a constant expression}}
-#else
- // c-local-error at +2 {{expression is not an integer constant expression}}
-#endif
+ // cpp-local-error at +3 {{expression is not an integral constant expression}}
+ // cpp-local-note at +2 {{function parameter 'A' with unknown value cannot be used in a constant expression}}
+ // c-local-error at +1 {{expression is not an integer constant expression}}
[[clang::code_align(A)]]
for(int I=0; I<128; ++I) { bar(I); }
}
-#if __cplusplus >= 201103L
void check_code_align_expression() {
int a[10];
@@ -97,24 +84,26 @@ void check_code_align_expression() {
for (int i = 0; i != 10; ++i)
a[i] = 0;
+#if __cplusplus >= 201103L
// Test that checks expression is a constant expression.
constexpr int bars = 0;
[[clang::code_align(bars + 1)]]
for (int i = 0; i != 10; ++i)
a[i] = 0;
+#endif
}
+#if __cplusplus >= 201103L
template <int A, int B, int C, int D>
void code_align_dependent() {
[[clang::code_align(C)]]
for(int I=0; I<128; ++I) { bar(I); }
- [[clang::code_align(A)]]
- // cpp-local-error at +1 {{duplicate loop attribute 'code_align'}}
- [[clang::code_align(B)]]
+ [[clang::code_align(A)]] // expected-note {{previous attribute is here}}
+ [[clang::code_align(B)]] // cpp-local-error {{duplicate loop attribute 'code_align'}}
for(int I=0; I<128; ++I) { bar(I); }
- // cpp-local-error at +2{{'code_align' attribute must be a constant power of two between 1 and 4096 inclusive}}
+ // cpp-local-error at +2{{'code_align' attribute requires a positive integral compile time constant expression}}
// cpp-local-note@#neg-instantiation {{in instantiation of function template specialization}}
[[clang::code_align(D)]]
for(int I=0; I<128; ++I) { bar(I); }
>From 9144e440b3898a24bad042158312643a29266cb6 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 6 Nov 2023 10:07:30 -0800
Subject: [PATCH 06/11] Fix clang format errors
---
clang/lib/Sema/SemaStmtAttr.cpp | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index a75b1d0b085bb34..e3671cee99422b0 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -344,7 +344,7 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
if (AlignValue > CodeAlignAttr::getMaxValue() || !ArgVal.isPowerOf2()) {
Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
<< CI << CodeAlignAttr::getMinValue() << CodeAlignAttr::getMaxValue()
- << AlignValue;
+ << AlignValue;
return nullptr;
}
}
@@ -358,16 +358,15 @@ static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
}
// Emit duplicate error for [[clang::code_align()]] attribute.
-static void
-CheckForDuplicateCodeAlignAttribute(Sema &S,
- const SmallVectorImpl<const Attr *> &Attrs) {
+static void CheckForDuplicateCodeAlignAttribute(
+ Sema &S, const SmallVectorImpl<const Attr *> &Attrs) {
const Attr *A = nullptr;
for (const auto *I : Attrs) {
if (isa<CodeAlignAttr>(I)) {
if (A) {
// Cannot specify same type of attribute twice.
S.Diag(I->getLocation(), diag::err_loop_attr_duplication) << A;
- S.Diag(A->getLocation(),diag::note_previous_attribute);
+ S.Diag(A->getLocation(), diag::note_previous_attribute);
}
A = I;
}
>From 22f66bd0199300a92ea2aefc66a2640e79b734a4 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 6 Nov 2023 11:56:08 -0800
Subject: [PATCH 07/11] Address review comments
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
clang/lib/CodeGen/CGLoopInfo.cpp | 10 ++++------
clang/lib/Sema/SemaStmtAttr.cpp | 10 ++--------
clang/test/Sema/code_align.c | 10 +++++-----
4 files changed, 12 insertions(+), 20 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8dab0bb996d0e9d..886458f5e946e6d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10030,7 +10030,7 @@ def err_loop_attr_duplication : Error<
"duplicate loop attribute %0">;
def err_attribute_power_of_two_in_range : Error<
"%0 attribute requires an integer argument which is a constant power of two "
- "between %1 and %2 inclusive - got %3">;
+ "between %1 and %2 inclusive; got %3">;
def warn_def_missing_case : Warning<"%plural{"
"1:enumeration value %1 not explicitly handled in switch|"
diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp
index a951198b925a513..0d4800b90a2f26c 100644
--- a/clang/lib/CodeGen/CGLoopInfo.cpp
+++ b/clang/lib/CodeGen/CGLoopInfo.cpp
@@ -800,12 +800,10 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
// Identify loop attribute 'code_align' from Attrs.
// For attribute code_align:
// n - 'llvm.loop.align i32 n' metadata will be emitted.
- for (const auto *A : Attrs) {
- if (const auto *CodeAlign = dyn_cast<CodeAlignAttr>(A)) {
- const auto *CE = cast<ConstantExpr>(CodeAlign->getAlignment());
- llvm::APSInt ArgVal = CE->getResultAsAPSInt();
- setCodeAlign(ArgVal.getSExtValue());
- }
+ if (const auto *CodeAlign = getSpecificAttr<const CodeAlignAttr>(Attrs)) {
+ const auto *CE = cast<ConstantExpr>(CodeAlign->getAlignment());
+ llvm::APSInt ArgVal = CE->getResultAsAPSInt();
+ setCodeAlign(ArgVal.getSExtValue());
}
setMustProgress(MustProgress);
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index e3671cee99422b0..96fa74427ee7852 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -331,17 +331,11 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
return nullptr;
E = Res.get();
- // This attribute requires a strictly positive value.
- if (ArgVal <= 0) {
- Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
- << CI << /*positive*/ 0;
- return nullptr;
- }
-
// This attribute requires an integer argument which is a constant power of
// two between 1 and 4096 inclusive.
int AlignValue = ArgVal.getSExtValue();
- if (AlignValue > CodeAlignAttr::getMaxValue() || !ArgVal.isPowerOf2()) {
+ if (AlignValue < CodeAlignAttr::getMinValue() ||
+ AlignValue > CodeAlignAttr::getMaxValue() || !ArgVal.isPowerOf2()) {
Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
<< CI << CodeAlignAttr::getMinValue() << CodeAlignAttr::getMaxValue()
<< AlignValue;
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index 715d2896969464b..51ecc070c672ed5 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -24,11 +24,11 @@ void bar(int);
// cpp-local-note at +1 {{declared here}}
void foo1(int A)
{
- // expected-error at +1 {{'code_align' attribute requires a positive integral compile time constant expression}}
+ // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got 0}}
[[clang::code_align(0)]]
for(int I=0; I<128; ++I) { bar(I); }
- // expected-error at +1 {{'code_align' attribute requires a positive integral compile time constant expression}}
+ // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got -4}}
[[clang::code_align(-4)]]
for(int I=0; I<128; ++I) { bar(I); }
@@ -58,11 +58,11 @@ void foo1(int A)
[[clang::code_align(64)]] // expected-error {{duplicate loop attribute 'code_align'}}
for(int I=0; I<128; ++I) { bar(I); }
- // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive - got 7}}
+ // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got 7}}
[[clang::code_align(7)]]
for(int I=0; I<128; ++I) { bar(I); }
- // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive - got 5000}}
+ // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got 5000}}
[[clang::code_align(5000)]]
for(int I=0; I<128; ++I) { bar(I); }
@@ -103,7 +103,7 @@ void code_align_dependent() {
[[clang::code_align(B)]] // cpp-local-error {{duplicate loop attribute 'code_align'}}
for(int I=0; I<128; ++I) { bar(I); }
- // cpp-local-error at +2{{'code_align' attribute requires a positive integral compile time constant expression}}
+ // cpp-local-error at +2{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got -10}}
// cpp-local-note@#neg-instantiation {{in instantiation of function template specialization}}
[[clang::code_align(D)]]
for(int I=0; I<128; ++I) { bar(I); }
>From 66f6269c4c00825e6f839fd9b6c1c204600e06b7 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 6 Nov 2023 19:28:02 -0800
Subject: [PATCH 08/11] Fix lit test failure
---
clang/test/Sema/code_align.c | 41 ++++++++++++++++++------------------
1 file changed, 21 insertions(+), 20 deletions(-)
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index 51ecc070c672ed5..ad8ec603a4d19e1 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -9,7 +9,7 @@ void foo() {
for (i = 0; i < 10; ++i) { // this is OK
a[i] = b[i] = 0;
}
- // expected-error at +1 {{'code_align' attribute only applies to 'for', 'while', and 'do' statements}}
+ // expected-error at +1{{'code_align' attribute only applies to 'for', 'while', and 'do' statements}}
[[clang::code_align(4)]]
i = 7;
for (i = 0; i < 10; ++i) {
@@ -21,27 +21,27 @@ void foo() {
}
void bar(int);
-// cpp-local-note at +1 {{declared here}}
+// cpp-local-note at +1{{declared here}}
void foo1(int A)
{
- // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got 0}}
+ // expected-error at +1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got 0}}
[[clang::code_align(0)]]
for(int I=0; I<128; ++I) { bar(I); }
- // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got -4}}
+ // expected-error at +1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got -4}}
[[clang::code_align(-4)]]
for(int I=0; I<128; ++I) { bar(I); }
- // cpp-local-error at +2 {{integral constant expression must have integral or unscoped enumeration type, not 'double'}}
- // c-local-error at +1 {{integer constant expression must have integer type, not 'double'}}
+ // cpp-local-error at +2{{integral constant expression must have integral or unscoped enumeration type, not 'double'}}
+ // c-local-error at +1{{integer constant expression must have integer type, not 'double'}}
[[clang::code_align(64.0)]]
for(int I=0; I<128; ++I) { bar(I); }
- // expected-error at +1 {{'code_align' attribute takes one argument}}
+ // expected-error at +1{{'code_align' attribute takes one argument}}
[[clang::code_align()]]
for(int I=0; I<128; ++I) { bar(I); }
- // expected-error at +1 {{'code_align' attribute takes one argument}}
+ // expected-error at +1{{'code_align' attribute takes one argument}}
[[clang::code_align(4,8)]]
for(int I=0; I<128; ++I) { bar(I); }
@@ -49,26 +49,26 @@ void foo1(int A)
[[clang::code_align(32)]]
for(int I=0; I<128; ++I) { bar(I); }
- // cpp-local-error at +2 {{integral constant expression must have integral or unscoped enumeration type, not 'const char[4]'}}
- // c-local-error at +1 {{integer constant expression must have integer type, not 'char[4]'}}
+ // cpp-local-error at +2{{integral constant expression must have integral or unscoped enumeration type, not 'const char[4]'}}
+ // c-local-error at +1{{integer constant expression must have integer type, not 'char[4]'}}
[[clang::code_align("abc")]]
for(int I=0; I<128; ++I) { bar(I); }
- [[clang::code_align(64)]] // expected-note {{previous attribute is here}}
- [[clang::code_align(64)]] // expected-error {{duplicate loop attribute 'code_align'}}
+ [[clang::code_align(64)]] // expected-note{{previous attribute is here}}
+ [[clang::code_align(64)]] // expected-error{{duplicate loop attribute 'code_align'}}
for(int I=0; I<128; ++I) { bar(I); }
- // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got 7}}
+ // expected-error at +1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got 7}}
[[clang::code_align(7)]]
for(int I=0; I<128; ++I) { bar(I); }
- // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got 5000}}
+ // expected-error at +1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got 5000}}
[[clang::code_align(5000)]]
for(int I=0; I<128; ++I) { bar(I); }
- // cpp-local-error at +3 {{expression is not an integral constant expression}}
- // cpp-local-note at +2 {{function parameter 'A' with unknown value cannot be used in a constant expression}}
- // c-local-error at +1 {{expression is not an integer constant expression}}
+ // cpp-local-error at +3{{expression is not an integral constant expression}}
+ // cpp-local-note at +2{{function parameter 'A' with unknown value cannot be used in a constant expression}}
+ // c-local-error at +1{{expression is not an integer constant expression}}
[[clang::code_align(A)]]
for(int I=0; I<128; ++I) { bar(I); }
}
@@ -78,6 +78,7 @@ void check_code_align_expression() {
// Test that checks expression is not a constant expression.
int foo2; // cpp-local-note {{declared here}}
+ // c-local-error at +3{{expression is not an integer constant expression}}
// cpp-local-error at +2{{expression is not an integral constant expression}}
// cpp-local-note at +1{{read of non-const variable 'foo2' is not allowed in a constant expression}}
[[clang::code_align(foo2 + 1)]]
@@ -99,12 +100,12 @@ void code_align_dependent() {
[[clang::code_align(C)]]
for(int I=0; I<128; ++I) { bar(I); }
- [[clang::code_align(A)]] // expected-note {{previous attribute is here}}
- [[clang::code_align(B)]] // cpp-local-error {{duplicate loop attribute 'code_align'}}
+ [[clang::code_align(A)]] // expected-note{{previous attribute is here}}
+ [[clang::code_align(B)]] // cpp-local-error{{duplicate loop attribute 'code_align'}}
for(int I=0; I<128; ++I) { bar(I); }
// cpp-local-error at +2{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; got -10}}
- // cpp-local-note@#neg-instantiation {{in instantiation of function template specialization}}
+ // cpp-local-note@#neg-instantiation{{in instantiation of function template specialization}}
[[clang::code_align(D)]]
for(int I=0; I<128; ++I) { bar(I); }
}
>From 3ac064bc26a516a81b2ff36ec0dc9c55350c3e3f Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 6 Nov 2023 20:23:07 -0800
Subject: [PATCH 09/11] Fix DuplicateCodeAlignAttrs check
---
clang/lib/Sema/SemaStmtAttr.cpp | 38 +++++++++++++++++++++++----------
1 file changed, 27 insertions(+), 11 deletions(-)
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 96fa74427ee7852..253b6378953b485 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -352,17 +352,33 @@ static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
}
// Emit duplicate error for [[clang::code_align()]] attribute.
-static void CheckForDuplicateCodeAlignAttribute(
- Sema &S, const SmallVectorImpl<const Attr *> &Attrs) {
- const Attr *A = nullptr;
- for (const auto *I : Attrs) {
- if (isa<CodeAlignAttr>(I)) {
- if (A) {
- // Cannot specify same type of attribute twice.
- S.Diag(I->getLocation(), diag::err_loop_attr_duplication) << A;
- S.Diag(A->getLocation(), diag::note_previous_attribute);
- }
- A = I;
+static void
+CheckForDuplicateCodeAlignAttrs(Sema &S,
+ ArrayRef<const Attr *> Attrs) {
+ // Create a list of CodeAlign attributes only.
+ SmallVector<const CodeAlignAttr *, 8> OnlyCodeAlignAttrs;
+ llvm::transform(
+ Attrs, std::back_inserter(OnlyCodeAlignAttrs), [](const Attr *A) {
+ return dyn_cast_or_null<const CodeAlignAttr>(A);
+ });
+ OnlyCodeAlignAttrs.erase(
+ std::remove(OnlyCodeAlignAttrs.begin(), OnlyCodeAlignAttrs.end(),
+ static_cast<CodeAlignAttr *>(nullptr)),
+ OnlyCodeAlignAttrs.end());
+ if (OnlyCodeAlignAttrs.empty())
+ return;
+
+ for (const auto *I : OnlyCodeAlignAttrs) {
+ const auto *OtherAttrItr =
+ llvm::find_if(OnlyCodeAlignAttrs, [](const CodeAlignAttr *A) {
+ return isa<CodeAlignAttr>(A);
+ });
+
+ const CodeAlignAttr *OtherAttr =
+ OtherAttrItr == OnlyCodeAlignAttrs.end() ? nullptr : *OtherAttrItr;
+ if (OtherAttr != I) {
+ S.Diag(I->getLocation(), diag::err_loop_attr_duplication) << OtherAttr;
+ S.Diag(OtherAttr->getLocation(), diag::note_previous_attribute);
}
}
}
>From 172e2385edfb3f87b8c80c5d96a8fbb7c52e805d Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 6 Nov 2023 20:42:01 -0800
Subject: [PATCH 10/11] Fix Clang format errors
---
clang/lib/Sema/SemaStmtAttr.cpp | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 253b6378953b485..a3042a380913329 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -352,27 +352,26 @@ static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
}
// Emit duplicate error for [[clang::code_align()]] attribute.
-static void
-CheckForDuplicateCodeAlignAttrs(Sema &S,
- ArrayRef<const Attr *> Attrs) {
+static void CheckForDuplicateCodeAlignAttrs(Sema &S,
+ ArrayRef<const Attr *> Attrs) {
// Create a list of CodeAlign attributes only.
SmallVector<const CodeAlignAttr *, 8> OnlyCodeAlignAttrs;
llvm::transform(
- Attrs, std::back_inserter(OnlyCodeAlignAttrs), [](const Attr *A) {
- return dyn_cast_or_null<const CodeAlignAttr>(A);
- });
- OnlyCodeAlignAttrs.erase(
- std::remove(OnlyCodeAlignAttrs.begin(), OnlyCodeAlignAttrs.end(),
- static_cast<CodeAlignAttr *>(nullptr)),
- OnlyCodeAlignAttrs.end());
+ Attrs, std::back_inserter(OnlyCodeAlignAttrs),
+ [](const Attr *A) { return dyn_cast_or_null<const CodeAlignAttr>(A); });
+ OnlyCodeAlignAttrs.erase(std::remove(OnlyCodeAlignAttrs.begin(),
+ OnlyCodeAlignAttrs.end(),
+ static_cast<CodeAlignAttr *>(nullptr)),
+ OnlyCodeAlignAttrs.end());
+
if (OnlyCodeAlignAttrs.empty())
return;
for (const auto *I : OnlyCodeAlignAttrs) {
const auto *OtherAttrItr =
- llvm::find_if(OnlyCodeAlignAttrs, [](const CodeAlignAttr *A) {
- return isa<CodeAlignAttr>(A);
- });
+ llvm::find_if(OnlyCodeAlignAttrs, [](const CodeAlignAttr *A) {
+ return isa<CodeAlignAttr>(A);
+ });
const CodeAlignAttr *OtherAttr =
OtherAttrItr == OnlyCodeAlignAttrs.end() ? nullptr : *OtherAttrItr;
>From c8d5270bc4eca6a6b9c6beedbf00c92fa502f487 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 6 Nov 2023 20:52:56 -0800
Subject: [PATCH 11/11] Remove wrong function
---
clang/lib/Sema/SemaStmtAttr.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index a3042a380913329..81b25fd1bbe20d4 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -603,5 +603,5 @@ void Sema::ProcessStmtAttributes(Stmt *S, const ParsedAttributes &InAttrs,
}
CheckForIncompatibleAttributes(*this, OutAttrs);
- CheckForDuplicateCodeAlignAttribute(*this, OutAttrs);
+ CheckForDuplicateCodeAlignAttrs(*this, OutAttrs);
}
More information about the cfe-commits
mailing list