[flang] [clang-tools-extra] [compiler-rt] [clang] [llvm] [clang] Add support for new loop attribute [[clang::code_align()]] (PR #70762)

via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 20 10:18:48 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/39] [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/39] 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/39] 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/39] 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/39] 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/39] 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/39] 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/39] 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/39] 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/39] 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/39] 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);
 }

>From 2e6ee337a76ace24d22351475da366d193393312 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 13 Nov 2023 09:53:12 -0800
Subject: [PATCH 12/39] Update diagnostic message and test

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td |  2 +-
 clang/test/Sema/code_align.c                     | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 83993def97c350d..27d322e1d46e622 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10029,7 +10029,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; provided argument was %3">;
 
 def warn_def_missing_case : Warning<"%plural{"
   "1:enumeration value %1 not explicitly handled in switch|"
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index ad8ec603a4d19e1..07bb50f7574c825 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 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; provided argument was 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; provided argument was -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; provided argument was 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; provided argument was 5000}}
   [[clang::code_align(5000)]]
   for(int I=0; I<128; ++I) { bar(I); }
 
@@ -104,7 +104,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 an integer argument which is a constant power of two between 1 and 4096 inclusive; got -10}}
+  // cpp-local-error at +2{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was -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 84748604e3a392d6d3a4f2559992d63b485bb647 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 13 Nov 2023 10:59:49 -0800
Subject: [PATCH 13/39] Update min and max aligment check

---
 clang/include/clang/Basic/Attr.td | 8 --------
 clang/lib/Sema/SemaStmtAttr.cpp   | 9 +++++----
 2 files changed, 5 insertions(+), 12 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 51d92c662743885..6ab206039d91812 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4304,12 +4304,4 @@ def CodeAlign: StmtAttr {
                               ErrorDiag, "'for', 'while', and 'do' statements">;
   let Args = [ExprArgument<"Alignment">];
   let Documentation = [CodeAlignAttrDocs];
-  let AdditionalMembers = [{
-    static int getMinValue() {
-      return 1;
-    }
-    static int getMaxValue() {
-      return 4096;
-    }
-  }];
 }
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 81b25fd1bbe20d4..9dafc90557a86c4 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -334,11 +334,12 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
     // 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::getMinValue() ||
-        AlignValue > CodeAlignAttr::getMaxValue() || !ArgVal.isPowerOf2()) {
+    static int MaximumAlignment = 4096;
+    static int MinimumAlignment = 1;
+    if (AlignValue < MinimumAlignment ||
+        AlignValue > MaximumAlignment || !ArgVal.isPowerOf2()) {
       Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
-          << CI << CodeAlignAttr::getMinValue() << CodeAlignAttr::getMaxValue()
-          << AlignValue;
+          << CI << MinimumAlignment << MaximumAlignment << AlignValue;
       return nullptr;
     }
   }

>From aa85ed1ede892c7da3d5c2dee5886dd0e2ad0cb7 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 13 Nov 2023 11:42:01 -0800
Subject: [PATCH 14/39] Add additional members as static-constexpr

---
 clang/include/clang/Basic/Attr.td | 4 ++++
 clang/lib/Sema/SemaStmtAttr.cpp   | 9 ++++-----
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 6ab206039d91812..fddd425356d3283 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4304,4 +4304,8 @@ def CodeAlign: StmtAttr {
                               ErrorDiag, "'for', 'while', and 'do' statements">;
   let Args = [ExprArgument<"Alignment">];
   let Documentation = [CodeAlignAttrDocs];
+  let AdditionalMembers = [{
+    static constexpr int MinimumAlignment = 1;
+    static constexpr int MaximumAlignment = 4096;
+  }];
 }
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 9dafc90557a86c4..df3d37327c2e0a0 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -334,12 +334,11 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
     // This attribute requires an integer argument which is a constant power of
     // two between 1 and 4096 inclusive.
     int AlignValue = ArgVal.getSExtValue();
-    static int MaximumAlignment = 4096;
-    static int MinimumAlignment = 1;
-    if (AlignValue < MinimumAlignment ||
-        AlignValue > MaximumAlignment || !ArgVal.isPowerOf2()) {
+    if (AlignValue < CodeAlignAttr::MinimumAlignment ||
+        AlignValue > CodeAlignAttr::MaximumAlignment || !ArgVal.isPowerOf2()) {
       Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
-          << CI << MinimumAlignment << MaximumAlignment << AlignValue;
+          << CI << CodeAlignAttr::MinimumAlignment
+          << CodeAlignAttr::MaximumAlignment << AlignValue;
       return nullptr;
     }
   }

>From 088767463be990eb8af4e62a6c66cf4ba06613c3 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 13 Nov 2023 19:48:36 -0800
Subject: [PATCH 15/39] Address review comments

---
 clang/lib/Sema/SemaStmtAttr.cpp | 13 +++++++++----
 clang/test/Sema/code_align.c    | 17 +++++++++++++++++
 2 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index df3d37327c2e0a0..58c676e83036228 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -333,12 +333,17 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
 
     // 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::MinimumAlignment ||
-        AlignValue > CodeAlignAttr::MaximumAlignment || !ArgVal.isPowerOf2()) {
+    if (ArgVal < CodeAlignAttr::MinimumAlignment) {
       Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
           << CI << CodeAlignAttr::MinimumAlignment
-          << CodeAlignAttr::MaximumAlignment << AlignValue;
+          << CodeAlignAttr::MaximumAlignment << ArgVal.getSExtValue();
+      return nullptr;
+    }
+
+    if (ArgVal > CodeAlignAttr::MaximumAlignment || !ArgVal.isPowerOf2()) {
+      Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
+          << CI << CodeAlignAttr::MinimumAlignment
+          << CodeAlignAttr::MaximumAlignment << ArgVal.getZExtValue();
       return nullptr;
     }
   }
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index 07bb50f7574c825..0ef606e7ffec36a 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -66,6 +66,23 @@ void foo1(int A)
   [[clang::code_align(5000)]]
   for(int I=0; I<128; ++I) { bar(I); }
 
+  // expected-warning at +2 {{integer literal is too large to be represented in a signed integer type, interpreting as unsigned}}
+  // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was 9223372036854775808}}
+  [[clang::code_align(9223372036854775808)]]
+  for(int I=0; I<256; ++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; provided argument was 0}}
+  [[clang::code_align((__int128_t)0x1234567890abcde0ULL << 64)]]
+  for(int I=0; I<256; ++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; provided argument was 1311768467294899680}}
+  [[clang::code_align((__int128_t)0x1234567890abcde0ULL)]]
+  for(int I=0; I<256; ++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; provided argument was 32768}}
+  [[clang::code_align(32768)]]
+  for(int I=0; I<256; ++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}}

>From 48e00f156a68b420ea402d3c555f360976c5fc12 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 13 Nov 2023 21:52:18 -0800
Subject: [PATCH 16/39] Fix test

---
 clang/test/Sema/code_align.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index 0ef606e7ffec36a..d5f83f0438f2470 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -75,10 +75,6 @@ void foo1(int A)
   [[clang::code_align((__int128_t)0x1234567890abcde0ULL << 64)]]
   for(int I=0; I<256; ++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; provided argument was 1311768467294899680}}
-  [[clang::code_align((__int128_t)0x1234567890abcde0ULL)]]
-  for(int I=0; I<256; ++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; provided argument was 32768}}
   [[clang::code_align(32768)]]
   for(int I=0; I<256; ++I) { bar(I); }

>From 8fb7d2287fb69ec2964e25f057c4cba67bc119de Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 13 Nov 2023 22:31:59 -0800
Subject: [PATCH 17/39] Fix lit test failures

---
 clang/test/Sema/code_align.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index d5f83f0438f2470..e1fd9e2fd625393 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -75,10 +75,6 @@ void foo1(int A)
   [[clang::code_align((__int128_t)0x1234567890abcde0ULL << 64)]]
   for(int I=0; I<256; ++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; provided argument was 32768}}
-  [[clang::code_align(32768)]]
-  for(int I=0; I<256; ++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}}

>From 8bec3c455b5f55b40a8a3d8c9180c0e3d52765fa Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Tue, 14 Nov 2023 17:30:49 -0800
Subject: [PATCH 18/39] Fix bug for alignment value with
 ((__int128_t)0x1234567890abcde0ULL << 64)

---
 clang/lib/Sema/SemaStmtAttr.cpp | 25 +++++++++++++++++--------
 clang/test/Sema/code_align.c    |  2 +-
 2 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 58c676e83036228..6cb21cda2cfa673 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -322,6 +322,7 @@ 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()) {
@@ -333,18 +334,26 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
 
     // This attribute requires an integer argument which is a constant power of
     // two between 1 and 4096 inclusive.
-    if (ArgVal < CodeAlignAttr::MinimumAlignment) {
+    if ((ArgVal < CodeAlignAttr::MinimumAlignment ||
+	 ArgVal < CodeAlignAttr::MaximumAlignment) && !ArgVal.isPowerOf2()) {
       Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
-          << CI << CodeAlignAttr::MinimumAlignment
-          << CodeAlignAttr::MaximumAlignment << ArgVal.getSExtValue();
+         << CI << CodeAlignAttr::MinimumAlignment
+         << CodeAlignAttr::MaximumAlignment << ArgVal.getSExtValue();
       return nullptr;
     }
 
-    if (ArgVal > CodeAlignAttr::MaximumAlignment || !ArgVal.isPowerOf2()) {
-      Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
-          << CI << CodeAlignAttr::MinimumAlignment
-          << CodeAlignAttr::MaximumAlignment << ArgVal.getZExtValue();
-      return nullptr;
+    if (ArgVal > CodeAlignAttr::MaximumAlignment) {
+      if (ArgVal > std::numeric_limits<int32_t>::max() && !ArgVal.isPowerOf2()) {
+        Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
+           << CI << CodeAlignAttr::MinimumAlignment
+           << CodeAlignAttr::MaximumAlignment
+           << std::numeric_limits<int32_t>::max();
+      }	else {
+        Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
+           << CI << CodeAlignAttr::MinimumAlignment
+           << CodeAlignAttr::MaximumAlignment << ArgVal.getZExtValue();
+        return nullptr;
+      }
     }
   }
   return new (Context) CodeAlignAttr(Context, CI, E);
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index e1fd9e2fd625393..ba37d3e0fb27321 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -71,7 +71,7 @@ void foo1(int A)
   [[clang::code_align(9223372036854775808)]]
   for(int I=0; I<256; ++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; provided argument was 0}}
+  // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was 2147483647}}
   [[clang::code_align((__int128_t)0x1234567890abcde0ULL << 64)]]
   for(int I=0; I<256; ++I) { bar(I); }
 

>From 5c4ce9e76828bcfd5372441da250686ab2995001 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Tue, 14 Nov 2023 17:46:34 -0800
Subject: [PATCH 19/39] Fix clang format errors

---
 clang/lib/Sema/SemaStmtAttr.cpp | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 6cb21cda2cfa673..335743a72a7a098 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -322,7 +322,6 @@ 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()) {
@@ -335,23 +334,25 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
     // This attribute requires an integer argument which is a constant power of
     // two between 1 and 4096 inclusive.
     if ((ArgVal < CodeAlignAttr::MinimumAlignment ||
-	 ArgVal < CodeAlignAttr::MaximumAlignment) && !ArgVal.isPowerOf2()) {
+         ArgVal < CodeAlignAttr::MaximumAlignment) &&
+         !ArgVal.isPowerOf2()) {
       Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
-         << CI << CodeAlignAttr::MinimumAlignment
-         << CodeAlignAttr::MaximumAlignment << ArgVal.getSExtValue();
+          << CI << CodeAlignAttr::MinimumAlignment
+          << CodeAlignAttr::MaximumAlignment << ArgVal.getSExtValue();
       return nullptr;
     }
 
     if (ArgVal > CodeAlignAttr::MaximumAlignment) {
-      if (ArgVal > std::numeric_limits<int32_t>::max() && !ArgVal.isPowerOf2()) {
+      if (ArgVal > std::numeric_limits<int32_t>::max() &&
+          !ArgVal.isPowerOf2()) {
         Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
-           << CI << CodeAlignAttr::MinimumAlignment
-           << CodeAlignAttr::MaximumAlignment
-           << std::numeric_limits<int32_t>::max();
-      }	else {
+            << CI << CodeAlignAttr::MinimumAlignment
+            << CodeAlignAttr::MaximumAlignment
+            << std::numeric_limits<int32_t>::max();
+      } else {
         Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
-           << CI << CodeAlignAttr::MinimumAlignment
-           << CodeAlignAttr::MaximumAlignment << ArgVal.getZExtValue();
+            << CI << CodeAlignAttr::MinimumAlignment
+            << CodeAlignAttr::MaximumAlignment << ArgVal.getZExtValue();
         return nullptr;
       }
     }

>From 974ebf2ce521ef076a76ed60c1382320d20360ff Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Tue, 14 Nov 2023 18:05:26 -0800
Subject: [PATCH 20/39] update patch

---
 clang/lib/Sema/SemaStmtAttr.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 335743a72a7a098..07be376285a42e5 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -333,9 +333,8 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
 
     // This attribute requires an integer argument which is a constant power of
     // two between 1 and 4096 inclusive.
-    if ((ArgVal < CodeAlignAttr::MinimumAlignment ||
-         ArgVal < CodeAlignAttr::MaximumAlignment) &&
-         !ArgVal.isPowerOf2()) {
+    if (ArgVal < CodeAlignAttr::MinimumAlignment ||
+        (ArgVal < CodeAlignAttr::MaximumAlignment && !ArgVal.isPowerOf2())) {
       Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
           << CI << CodeAlignAttr::MinimumAlignment
           << CodeAlignAttr::MaximumAlignment << ArgVal.getSExtValue();

>From 06eadd96a7d8a5e084af56e77b6aa2a41cdead5e Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Wed, 15 Nov 2023 06:08:07 -0800
Subject: [PATCH 21/39] Fix return nullptr check

---
 clang/lib/Sema/SemaStmtAttr.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 07be376285a42e5..a363640501aec43 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -348,6 +348,7 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
             << CI << CodeAlignAttr::MinimumAlignment
             << CodeAlignAttr::MaximumAlignment
             << std::numeric_limits<int32_t>::max();
+        return nullptr;
       } else {
         Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
             << CI << CodeAlignAttr::MinimumAlignment

>From 5ebb42f3105186ffde314496bd9203bca5f18c45 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Wed, 15 Nov 2023 09:05:04 -0800
Subject: [PATCH 22/39] Update patch with trySExtValue() and add test case for
 big negative alignment value

---
 clang/lib/Sema/SemaStmtAttr.cpp |  8 +++-----
 clang/test/Sema/code_align.c    | 10 +++++++---
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index a363640501aec43..2f65b491ebb6662 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -341,13 +341,11 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
       return nullptr;
     }
 
-    if (ArgVal > CodeAlignAttr::MaximumAlignment) {
-      if (ArgVal > std::numeric_limits<int32_t>::max() &&
-          !ArgVal.isPowerOf2()) {
+     if (ArgVal > CodeAlignAttr::MaximumAlignment) {
+      if (!ArgVal.trySExtValue()) {
         Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
             << CI << CodeAlignAttr::MinimumAlignment
-            << CodeAlignAttr::MaximumAlignment
-            << std::numeric_limits<int32_t>::max();
+            << CodeAlignAttr::MaximumAlignment << E;
         return nullptr;
       } else {
         Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index ba37d3e0fb27321..7b11c30522d9ac0 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -66,15 +66,19 @@ void foo1(int A)
   [[clang::code_align(5000)]]
   for(int I=0; I<128; ++I) { bar(I); }
 
-  // expected-warning at +2 {{integer literal is too large to be represented in a signed integer type, interpreting as unsigned}}
-  // expected-error at +1 {{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was 9223372036854775808}}
+  // expected-warning at +2{{integer literal is too large to be represented in a signed integer type, interpreting as unsigned}}
+  // expected-error at +1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was 9223372036854775808}}
   [[clang::code_align(9223372036854775808)]]
   for(int I=0; I<256; ++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; provided argument was 2147483647}}
+  // expected-error at +1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was (__int128_t)1311768467294899680ULL << 64}}
   [[clang::code_align((__int128_t)0x1234567890abcde0ULL << 64)]]
   for(int I=0; I<256; ++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; provided argument was -922337203685477}}
+  [[clang::code_align(-922337203685477)]]
+  for(int I=0; I<256; ++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}}

>From ebcefed69f0357c869762c22bfc78ab5baaeaddd Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Wed, 15 Nov 2023 10:43:30 -0800
Subject: [PATCH 23/39] Check an expression resulting in a negative that takes
 more than 64 bits for negative cases

---
 clang/lib/Sema/SemaStmtAttr.cpp | 21 ++++++++++++++++-----
 clang/test/Sema/code_align.c    |  4 ++++
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 2f65b491ebb6662..06d414e06925686 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -333,15 +333,26 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
 
     // This attribute requires an integer argument which is a constant power of
     // two between 1 and 4096 inclusive.
+    // Check if an expression resulting in a negative/positive cases that take
+    // more than 64 bits.
+    // Print the actual alignment value passing to the attribute if it is less
+    // than 64 bits otherwise print the expression.
     if (ArgVal < CodeAlignAttr::MinimumAlignment ||
         (ArgVal < CodeAlignAttr::MaximumAlignment && !ArgVal.isPowerOf2())) {
-      Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
-          << CI << CodeAlignAttr::MinimumAlignment
-          << CodeAlignAttr::MaximumAlignment << ArgVal.getSExtValue();
-      return nullptr;
+      if (!ArgVal.trySExtValue()) {
+        Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
+            << CI << CodeAlignAttr::MinimumAlignment
+            << CodeAlignAttr::MaximumAlignment << E;
+        return nullptr;
+      } else {
+        Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
+            << CI << CodeAlignAttr::MinimumAlignment
+            << CodeAlignAttr::MaximumAlignment << ArgVal.getSExtValue();
+        return nullptr;
+      }
     }
 
-     if (ArgVal > CodeAlignAttr::MaximumAlignment) {
+    if (ArgVal > CodeAlignAttr::MaximumAlignment) {
       if (!ArgVal.trySExtValue()) {
         Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
             << CI << CodeAlignAttr::MinimumAlignment
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index 7b11c30522d9ac0..9e9791229cd852f 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -79,6 +79,10 @@ void foo1(int A)
   [[clang::code_align(-922337203685477)]]
   for(int I=0; I<256; ++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; provided argument was -(__int128_t)1311768467294899680ULL << 64}}
+  [[clang::code_align(-(__int128_t)0x1234567890abcde0ULL << 64)]]
+  for(int I=0; I<256; ++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}}

>From 72a1a69528f7abffae1260dd3b59b60b914b3405 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Wed, 15 Nov 2023 11:02:20 -0800
Subject: [PATCH 24/39] Fix lit test

---
 clang/test/Sema/code_align.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index 9e9791229cd852f..fe51ed6f224b442 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -79,7 +79,9 @@ void foo1(int A)
   [[clang::code_align(-922337203685477)]]
   for(int I=0; I<256; ++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; provided argument was -(__int128_t)1311768467294899680ULL << 64}}
+  // cpp-local-error at +3{{expression is not an integral constant expression}}
+  // cpp-local-note at +2{{left shift of negative value -1311768467294899680}}
+  // c-local-error at +1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was -(__int128_t)1311768467294899680ULL << 64}}
   [[clang::code_align(-(__int128_t)0x1234567890abcde0ULL << 64)]]
   for(int I=0; I<256; ++I) { bar(I); }
 

>From 845b687599c710402bdbc22f183c93220ff0a4e1 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Wed, 15 Nov 2023 13:33:41 -0800
Subject: [PATCH 25/39] Fix assertion and remove duplicate codes

---
 clang/lib/Sema/SemaStmtAttr.cpp | 29 +++++------------------------
 clang/test/Sema/code_align.c    |  2 +-
 2 files changed, 6 insertions(+), 25 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 06d414e06925686..951d60b8a70e50d 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -333,37 +333,18 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
 
     // This attribute requires an integer argument which is a constant power of
     // two between 1 and 4096 inclusive.
-    // Check if an expression resulting in a negative/positive cases that take
-    // more than 64 bits.
-    // Print the actual alignment value passing to the attribute if it is less
-    // than 64 bits otherwise print the expression.
     if (ArgVal < CodeAlignAttr::MinimumAlignment ||
+	ArgVal > CodeAlignAttr::MaximumAlignment ||
         (ArgVal < CodeAlignAttr::MaximumAlignment && !ArgVal.isPowerOf2())) {
-      if (!ArgVal.trySExtValue()) {
+      if (std::optional<int64_t> Value = ArgVal.trySExtValue())
         Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
             << CI << CodeAlignAttr::MinimumAlignment
-            << CodeAlignAttr::MaximumAlignment << E;
-        return nullptr;
-      } else {
-        Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
-            << CI << CodeAlignAttr::MinimumAlignment
-            << CodeAlignAttr::MaximumAlignment << ArgVal.getSExtValue();
-        return nullptr;
-      }
-    }
-
-    if (ArgVal > CodeAlignAttr::MaximumAlignment) {
-      if (!ArgVal.trySExtValue()) {
+            << CodeAlignAttr::MaximumAlignment << Value.value();
+      else
         Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
             << CI << CodeAlignAttr::MinimumAlignment
             << CodeAlignAttr::MaximumAlignment << E;
-        return nullptr;
-      } else {
-        Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
-            << CI << CodeAlignAttr::MinimumAlignment
-            << CodeAlignAttr::MaximumAlignment << ArgVal.getZExtValue();
-        return nullptr;
-      }
+      return nullptr;
     }
   }
   return new (Context) CodeAlignAttr(Context, CI, E);
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index fe51ed6f224b442..52b380fa8c47437 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -67,7 +67,7 @@ void foo1(int A)
   for(int I=0; I<128; ++I) { bar(I); }
 
   // expected-warning at +2{{integer literal is too large to be represented in a signed integer type, interpreting as unsigned}}
-  // expected-error at +1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was 9223372036854775808}}
+  // expected-error at +1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was -9223372036854775808}}
   [[clang::code_align(9223372036854775808)]]
   for(int I=0; I<256; ++I) { bar(I); }
 

>From fca4436da0e91a643178bdfad8b535020ec04392 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Wed, 15 Nov 2023 13:49:25 -0800
Subject: [PATCH 26/39] Fix Clang format errors

---
 clang/lib/Sema/SemaStmtAttr.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 951d60b8a70e50d..1d95956a364ca27 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -334,8 +334,7 @@ CodeAlignAttr *Sema::BuildCodeAlignAttr(const AttributeCommonInfo &CI,
     // This attribute requires an integer argument which is a constant power of
     // two between 1 and 4096 inclusive.
     if (ArgVal < CodeAlignAttr::MinimumAlignment ||
-	ArgVal > CodeAlignAttr::MaximumAlignment ||
-        (ArgVal < CodeAlignAttr::MaximumAlignment && !ArgVal.isPowerOf2())) {
+        ArgVal > CodeAlignAttr::MaximumAlignment || !ArgVal.isPowerOf2()) {
       if (std::optional<int64_t> Value = ArgVal.trySExtValue())
         Diag(CI.getLoc(), diag::err_attribute_power_of_two_in_range)
             << CI << CodeAlignAttr::MinimumAlignment

>From a8b13eb4846d6f1cb41b12088aa371b3fe4edd24 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Wed, 15 Nov 2023 21:56:11 -0800
Subject: [PATCH 27/39] Use Simple algorithm to handle duplicate attribute
 values.

---
 clang/lib/Sema/SemaStmtAttr.cpp | 37 ++++++++++-----------------------
 1 file changed, 11 insertions(+), 26 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 1d95956a364ca27..a3bc33c41f7282c 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -356,32 +356,17 @@ 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) {
-  // 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);
+static void
+CheckForDuplicateCodeAlignAttrs(Sema &S,
+		                const SmallVectorImpl<const Attr *> &Attrs) {
+  const Attr *A = nullptr;
+  for (const auto *I : Attrs) {
+    if (isa<CodeAlignAttr>(I)) {
+      if (A) {
+        S.Diag(I->getLocation(), diag::err_loop_attr_duplication) << A;
+        S.Diag(A->getLocation(),diag::note_previous_attribute);
+      }
+      A = I;
     }
   }
 }

>From 488b8100a672cb7cb607a67fbcd36a2b95b90206 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Wed, 15 Nov 2023 22:13:52 -0800
Subject: [PATCH 28/39] Fix clang format errors

---
 clang/lib/Sema/SemaStmtAttr.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index a3bc33c41f7282c..3e70941077f7b9a 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -358,13 +358,13 @@ static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
 // Emit duplicate error for [[clang::code_align()]] attribute.
 static void
 CheckForDuplicateCodeAlignAttrs(Sema &S,
-		                const SmallVectorImpl<const Attr *> &Attrs) {
+                                const SmallVectorImpl<const Attr *> &Attrs) {
   const Attr *A = nullptr;
   for (const auto *I : Attrs) {
     if (isa<CodeAlignAttr>(I)) {
       if (A) {
         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 09b00c761f177c3c6ad2285fa5b7642f9c7d28cc Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Thu, 16 Nov 2023 11:04:19 -0800
Subject: [PATCH 29/39] Fix Duplicate Attribute Values diagnostic using
 find_if()

---
 clang/lib/Sema/SemaStmtAttr.cpp | 36 ++++++++++++++++++++++++---------
 1 file changed, 27 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 3e70941077f7b9a..56c964bfa01bdfc 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -359,16 +359,34 @@ static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
 static void
 CheckForDuplicateCodeAlignAttrs(Sema &S,
                                 const SmallVectorImpl<const Attr *> &Attrs) {
-  const Attr *A = nullptr;
-  for (const auto *I : Attrs) {
-    if (isa<CodeAlignAttr>(I)) {
-      if (A) {
-        S.Diag(I->getLocation(), diag::err_loop_attr_duplication) << A;
-        S.Diag(A->getLocation(), diag::note_previous_attribute);
-      }
-      A = I;
+    const auto *FirstItr =
+      std::find_if(Attrs.begin(), Attrs.end(), [](const Attr *A) {
+         return isa<const CodeAlignAttr>(A);
+      });
+
+    const Attr *FirstItrAttr =
+      FirstItr == Attrs.end() ? nullptr: *FirstItr;
+
+    if (FirstItr == Attrs.end()) // no attributes found
+      return;
+    const auto *NextItr =
+      std::find_if(FirstItr + 1, Attrs.end(), [](const Attr *A) {
+        return isa<const CodeAlignAttr>(A);
+      });
+    const Attr *NextItrAttr =
+      NextItr == Attrs.end() ? nullptr : *NextItr;
+    if (NextItr == Attrs.end()) // only 1 attribute found
+      return;
+
+    while (NextItr != Attrs.end()) {
+      // Diagnose
+      S.Diag(NextItrAttr->getLocation(), diag::err_loop_attr_duplication) << FirstItrAttr;
+      S.Diag(FirstItrAttr->getLocation(), diag::note_previous_attribute);
+      NextItr =
+	  std::find_if(NextItr + 1, Attrs.end(), [](const Attr *A) {
+            return isa<const CodeAlignAttr>(A);
+          });
     }
-  }
 }
 
 #define WANT_STMT_MERGE_LOGIC

>From 5fadd6a9b646136a8b0da919a7dace945bd6ff87 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Thu, 16 Nov 2023 11:41:19 -0800
Subject: [PATCH 30/39] Apply review comments

---
 clang/lib/Sema/SemaStmtAttr.cpp | 38 +++++++++++----------------------
 1 file changed, 13 insertions(+), 25 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 56c964bfa01bdfc..bad47c01a872ddd 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -359,34 +359,22 @@ static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
 static void
 CheckForDuplicateCodeAlignAttrs(Sema &S,
                                 const SmallVectorImpl<const Attr *> &Attrs) {
-    const auto *FirstItr =
-      std::find_if(Attrs.begin(), Attrs.end(), [](const Attr *A) {
-         return isa<const CodeAlignAttr>(A);
-      });
+  auto FindFunc = [](const Attr *A) {
+    return isa<const CodeAlignAttr>(A);
+  };
 
-    const Attr *FirstItrAttr =
-      FirstItr == Attrs.end() ? nullptr: *FirstItr;
+  const auto *FirstItr =
+    std::find_if(Attrs.begin(), Attrs.end(), FindFunc);
 
-    if (FirstItr == Attrs.end()) // no attributes found
-      return;
-    const auto *NextItr =
-      std::find_if(FirstItr + 1, Attrs.end(), [](const Attr *A) {
-        return isa<const CodeAlignAttr>(A);
-      });
-    const Attr *NextItrAttr =
-      NextItr == Attrs.end() ? nullptr : *NextItr;
-    if (NextItr == Attrs.end()) // only 1 attribute found
-      return;
+  if (FirstItr == Attrs.end()) // no attributes found
+    return;
 
-    while (NextItr != Attrs.end()) {
-      // Diagnose
-      S.Diag(NextItrAttr->getLocation(), diag::err_loop_attr_duplication) << FirstItrAttr;
-      S.Diag(FirstItrAttr->getLocation(), diag::note_previous_attribute);
-      NextItr =
-	  std::find_if(NextItr + 1, Attrs.end(), [](const Attr *A) {
-            return isa<const CodeAlignAttr>(A);
-          });
-    }
+  const auto *LastFoundItr = FirstItr;
+
+  while (Attrs.end() != (LastFoundItr = std::find_if(LastFoundItr + 1, Attrs.end(), FindFunc)))  {
+      S.Diag((*LastFoundItr)->getLocation(), diag::err_loop_attr_duplication) << *FirstItr;
+      S.Diag((*FirstItr)->getLocation(), diag::note_previous_attribute);
+  }
 }
 
 #define WANT_STMT_MERGE_LOGIC

>From 87bb3f2c5bca254417aef9a7d2aa67ff99b721f2 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Thu, 16 Nov 2023 11:48:39 -0800
Subject: [PATCH 31/39] Fix clang format errors

---
 clang/lib/Sema/SemaStmtAttr.cpp | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index bad47c01a872ddd..ecb854c04c08aa0 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -359,21 +359,19 @@ static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
 static void
 CheckForDuplicateCodeAlignAttrs(Sema &S,
                                 const SmallVectorImpl<const Attr *> &Attrs) {
-  auto FindFunc = [](const Attr *A) {
-    return isa<const CodeAlignAttr>(A);
-  };
-
-  const auto *FirstItr =
-    std::find_if(Attrs.begin(), Attrs.end(), FindFunc);
+  auto FindFunc = [](const Attr *A) { return isa<const CodeAlignAttr>(A); };
+  const auto *FirstItr = std::find_if(Attrs.begin(), Attrs.end(), FindFunc);
 
   if (FirstItr == Attrs.end()) // no attributes found
     return;
 
   const auto *LastFoundItr = FirstItr;
 
-  while (Attrs.end() != (LastFoundItr = std::find_if(LastFoundItr + 1, Attrs.end(), FindFunc)))  {
-      S.Diag((*LastFoundItr)->getLocation(), diag::err_loop_attr_duplication) << *FirstItr;
-      S.Diag((*FirstItr)->getLocation(), diag::note_previous_attribute);
+  while (Attrs.end() != (LastFoundItr = std::find_if(LastFoundItr + 1,
+                                                     Attrs.end(), FindFunc))) {
+    S.Diag((*LastFoundItr)->getLocation(), diag::err_loop_attr_duplication)
+        << *FirstItr;
+    S.Diag((*FirstItr)->getLocation(), diag::note_previous_attribute);
   }
 }
 

>From 8ad4686b94dea403ed0f3bc347a1a715df9aa72e Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Fri, 17 Nov 2023 09:56:47 -0800
Subject: [PATCH 32/39] Diagnose non-identical duplicates as a 'conflicting'
 loop attr and suppress identical duplicates

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  4 ++--
 clang/lib/Sema/SemaStmtAttr.cpp               | 22 +++++++++++++++----
 clang/test/Sema/code_align.c                  | 18 ++++++++++-----
 3 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 27d322e1d46e622..d3d1b117827930f 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10025,8 +10025,8 @@ 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_loop_attr_conflict : Error<
+  "conflicting 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; provided argument was %3">;
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index ecb854c04c08aa0..f14da32d5bf0f8f 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -355,7 +355,9 @@ static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
   return S.BuildCodeAlignAttr(A, E);
 }
 
-// Emit duplicate error for [[clang::code_align()]] attribute.
+// Diagnose non-identical duplicates as a 'conflicting' loop attr
+// and suppress duplicate errors in cases where the two match for
+// [[clang::code_align()]] attribute.
 static void
 CheckForDuplicateCodeAlignAttrs(Sema &S,
                                 const SmallVectorImpl<const Attr *> &Attrs) {
@@ -364,14 +366,26 @@ CheckForDuplicateCodeAlignAttrs(Sema &S,
 
   if (FirstItr == Attrs.end()) // no attributes found
     return;
-
   const auto *LastFoundItr = FirstItr;
 
   while (Attrs.end() != (LastFoundItr = std::find_if(LastFoundItr + 1,
                                                      Attrs.end(), FindFunc))) {
-    S.Diag((*LastFoundItr)->getLocation(), diag::err_loop_attr_duplication)
+
+    const auto *CEA = dyn_cast<ConstantExpr>(cast<CodeAlignAttr>(*FirstItr)->getAlignment());
+    const auto *CEB = dyn_cast<ConstantExpr>(cast<CodeAlignAttr>(*LastFoundItr)->getAlignment());
+    // If the value is dependent, we can not test anything.
+    if (!CEA || !CEB)
+      return;
+    // Test the attribute value.
+    std::optional<llvm::APSInt> FirstValue = CEA->getResultAsAPSInt();
+    llvm::APSInt SecondValue = CEB->getResultAsAPSInt();
+
+    if (FirstValue != SecondValue) {
+      S.Diag((*LastFoundItr)->getLocation(), diag::err_loop_attr_conflict)
         << *FirstItr;
-    S.Diag((*FirstItr)->getLocation(), diag::note_previous_attribute);
+      S.Diag((*FirstItr)->getLocation(), diag::note_previous_attribute);
+    }
+    return;
   }
 }
 
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index 52b380fa8c47437..d3490a41a668e3b 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -54,8 +54,12 @@ void foo1(int A)
   [[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)]] // OK
+  [[clang::code_align(64)]] // OK
+  for(int I=0; I<128; ++I) { bar(I); }
+
+  [[clang::code_align(8)]]  // expected-note{{previous attribute is here}}
+  [[clang::code_align(64)]] // expected-error{{conflicting 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; provided argument was 7}}
@@ -119,8 +123,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)]] // OK
+  [[clang::code_align(A)]] // OK
+  for(int I=0; I<128; ++I) { bar(I); }
+
+  // cpp-local-error at +1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was 23}}
+  [[clang::code_align(B)]]
   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; provided argument was -10}}
@@ -130,7 +138,7 @@ void code_align_dependent() {
 }
 
 int main() {
-  code_align_dependent<8, 16, 32, -10>(); // #neg-instantiation
+  code_align_dependent<8, 23, 32, -10>(); // #neg-instantiation
   return 0;
 }
 #endif

>From ac63c62cfaeebf55d814ab16f5419ce684c915e0 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Fri, 17 Nov 2023 10:47:15 -0800
Subject: [PATCH 33/39] Address review comments

---
 clang/lib/Sema/SemaStmtAttr.cpp | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index f14da32d5bf0f8f..b7d92dcf012b7e8 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -366,23 +366,24 @@ CheckForDuplicateCodeAlignAttrs(Sema &S,
 
   if (FirstItr == Attrs.end()) // no attributes found
     return;
+
   const auto *LastFoundItr = FirstItr;
+  std::optional<llvm::APSInt> FirstValue;
+
+  const auto *CEA = dyn_cast<ConstantExpr>(cast<CodeAlignAttr>(*FirstItr)->getAlignment());
+  // Return early if first alignment expression is dependent (since we don't know what the
+  // effective size will be), and skip the loop entirely.
+  if (!CEA)
+    return;
+  // Test the attribute value.
+  FirstValue = CEA->getResultAsAPSInt();
 
   while (Attrs.end() != (LastFoundItr = std::find_if(LastFoundItr + 1,
                                                      Attrs.end(), FindFunc))) {
-
-    const auto *CEA = dyn_cast<ConstantExpr>(cast<CodeAlignAttr>(*FirstItr)->getAlignment());
-    const auto *CEB = dyn_cast<ConstantExpr>(cast<CodeAlignAttr>(*LastFoundItr)->getAlignment());
-    // If the value is dependent, we can not test anything.
-    if (!CEA || !CEB)
-      return;
-    // Test the attribute value.
-    std::optional<llvm::APSInt> FirstValue = CEA->getResultAsAPSInt();
-    llvm::APSInt SecondValue = CEB->getResultAsAPSInt();
-
+    llvm::APSInt SecondValue = cast<ConstantExpr>(cast<CodeAlignAttr>(*LastFoundItr)->getAlignment())->getResultAsAPSInt();
     if (FirstValue != SecondValue) {
       S.Diag((*LastFoundItr)->getLocation(), diag::err_loop_attr_conflict)
-        << *FirstItr;
+          << *FirstItr;
       S.Diag((*FirstItr)->getLocation(), diag::note_previous_attribute);
     }
     return;

>From 8fd7bc1bc73a4bd132f0776b7644291726999dda Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Fri, 17 Nov 2023 10:52:06 -0800
Subject: [PATCH 34/39] Fix clang format errors

---
 clang/lib/Sema/SemaStmtAttr.cpp | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index b7d92dcf012b7e8..3df22d77fd56d3d 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -370,9 +370,10 @@ CheckForDuplicateCodeAlignAttrs(Sema &S,
   const auto *LastFoundItr = FirstItr;
   std::optional<llvm::APSInt> FirstValue;
 
-  const auto *CEA = dyn_cast<ConstantExpr>(cast<CodeAlignAttr>(*FirstItr)->getAlignment());
-  // Return early if first alignment expression is dependent (since we don't know what the
-  // effective size will be), and skip the loop entirely.
+  const auto *CEA =
+      dyn_cast<ConstantExpr>(cast<CodeAlignAttr>(*FirstItr)->getAlignment());
+  // Return early if first alignment expression is dependent (since we don't
+  // know what the effective size will be), and skip the loop entirely.
   if (!CEA)
     return;
   // Test the attribute value.
@@ -380,7 +381,9 @@ CheckForDuplicateCodeAlignAttrs(Sema &S,
 
   while (Attrs.end() != (LastFoundItr = std::find_if(LastFoundItr + 1,
                                                      Attrs.end(), FindFunc))) {
-    llvm::APSInt SecondValue = cast<ConstantExpr>(cast<CodeAlignAttr>(*LastFoundItr)->getAlignment())->getResultAsAPSInt();
+    llvm::APSInt SecondValue =
+        cast<ConstantExpr>(cast<CodeAlignAttr>(*LastFoundItr)->getAlignment())
+            ->getResultAsAPSInt();
     if (FirstValue != SecondValue) {
       S.Diag((*LastFoundItr)->getLocation(), diag::err_loop_attr_conflict)
           << *FirstItr;

>From 6a986a1e20a10a6ee817710a4ddbe25b02c4620b Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Fri, 17 Nov 2023 11:57:26 -0800
Subject: [PATCH 35/39] Fix crash and add dependence tests

---
 clang/lib/Sema/SemaStmtAttr.cpp | 18 +++++++++++-------
 clang/test/Sema/code_align.c    | 24 ++++++++++++++++++++++--
 2 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 3df22d77fd56d3d..f7a10689bb8f25d 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -370,20 +370,24 @@ CheckForDuplicateCodeAlignAttrs(Sema &S,
   const auto *LastFoundItr = FirstItr;
   std::optional<llvm::APSInt> FirstValue;
 
-  const auto *CEA =
+  const auto *CAFA =
       dyn_cast<ConstantExpr>(cast<CodeAlignAttr>(*FirstItr)->getAlignment());
   // Return early if first alignment expression is dependent (since we don't
   // know what the effective size will be), and skip the loop entirely.
-  if (!CEA)
+  if (!CAFA)
     return;
-  // Test the attribute value.
-  FirstValue = CEA->getResultAsAPSInt();
 
   while (Attrs.end() != (LastFoundItr = std::find_if(LastFoundItr + 1,
                                                      Attrs.end(), FindFunc))) {
-    llvm::APSInt SecondValue =
-        cast<ConstantExpr>(cast<CodeAlignAttr>(*LastFoundItr)->getAlignment())
-            ->getResultAsAPSInt();
+    const auto *CASA =
+	dyn_cast<ConstantExpr>(cast<CodeAlignAttr>(*LastFoundItr)->getAlignment());
+    // If the value is dependent, we can not test anything.
+    if (!CASA)
+      return;
+    // Test the attribute values.
+    llvm::APSInt SecondValue = CASA->getResultAsAPSInt();
+    FirstValue = CAFA->getResultAsAPSInt();
+
     if (FirstValue != SecondValue) {
       S.Diag((*LastFoundItr)->getLocation(), diag::err_loop_attr_conflict)
           << *FirstItr;
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index d3490a41a668e3b..4234b8da380fb9f 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -118,7 +118,7 @@ void check_code_align_expression() {
 }
 
 #if __cplusplus >= 201103L
-template <int A, int B, int C, int D>
+template <int A, int B, int C, int D, int E>
 void code_align_dependent() {
   [[clang::code_align(C)]]
   for(int I=0; I<128; ++I) { bar(I); }
@@ -127,6 +127,10 @@ void code_align_dependent() {
   [[clang::code_align(A)]] // OK
   for(int I=0; I<128; ++I) { bar(I); }
 
+  [[clang::code_align(A)]]
+  [[clang::code_align(E)]]
+  for(int I=0; I<128; ++I) { bar(I); }
+
   // cpp-local-error at +1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was 23}}
   [[clang::code_align(B)]]
   for(int I=0; I<128; ++I) { bar(I); }
@@ -137,8 +141,24 @@ void code_align_dependent() {
   for(int I=0; I<128; ++I) { bar(I); }
 }
 
+template<int ITMPL>
+void bar3() {
+  [[clang::code_align(8)]]
+  [[clang::code_align(ITMPL)]]
+  for(int I=0; I<128; ++I) { bar(I); }
+}
+
+template<int ITMPL1>
+void bar4() {
+  [[clang::code_align(ITMPL1)]]
+  [[clang::code_align(32)]]
+  for(int I=0; I<128; ++I) { bar(I); }
+}
+
 int main() {
-  code_align_dependent<8, 23, 32, -10>(); // #neg-instantiation
+  code_align_dependent<8, 23, 32, -10, 64>(); // #neg-instantiation
+  bar3 <4>();
+  bar4 <64>();
   return 0;
 }
 #endif

>From f32df3fa937801692571b6cd68c7ecab951ca9d1 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Fri, 17 Nov 2023 12:01:18 -0800
Subject: [PATCH 36/39] Address review comments

---
 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 f7a10689bb8f25d..df019ee4f25e302 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -386,7 +386,7 @@ CheckForDuplicateCodeAlignAttrs(Sema &S,
       return;
     // Test the attribute values.
     llvm::APSInt SecondValue = CASA->getResultAsAPSInt();
-    FirstValue = CAFA->getResultAsAPSInt();
+    if (!FirstValue) FirstValue = CAFA->getResultAsAPSInt();
 
     if (FirstValue != SecondValue) {
       S.Diag((*LastFoundItr)->getLocation(), diag::err_loop_attr_conflict)

>From d5ee5c17f7b5c6ce887bb6245e69b0a46e1d5c84 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Fri, 17 Nov 2023 12:23:50 -0800
Subject: [PATCH 37/39] Fix clang format errors

---
 clang/lib/Sema/SemaStmtAttr.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index df019ee4f25e302..e6dedd650a3cc77 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -379,14 +379,15 @@ CheckForDuplicateCodeAlignAttrs(Sema &S,
 
   while (Attrs.end() != (LastFoundItr = std::find_if(LastFoundItr + 1,
                                                      Attrs.end(), FindFunc))) {
-    const auto *CASA =
-	dyn_cast<ConstantExpr>(cast<CodeAlignAttr>(*LastFoundItr)->getAlignment());
+    const auto *CASA = dyn_cast<ConstantExpr>(
+        cast<CodeAlignAttr>(*LastFoundItr)->getAlignment());
     // If the value is dependent, we can not test anything.
     if (!CASA)
       return;
     // Test the attribute values.
     llvm::APSInt SecondValue = CASA->getResultAsAPSInt();
-    if (!FirstValue) FirstValue = CAFA->getResultAsAPSInt();
+    if (!FirstValue)
+      FirstValue = CAFA->getResultAsAPSInt();
 
     if (FirstValue != SecondValue) {
       S.Diag((*LastFoundItr)->getLocation(), diag::err_loop_attr_conflict)

>From 6778154ef0d64052f62b75955a615d542bafb799 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 20 Nov 2023 10:13:01 -0800
Subject: [PATCH 38/39] Fix diagnostic issues with conflicting attributes for
 template cases

---
 clang/include/clang/Sema/Sema.h |  1 +
 clang/lib/Sema/SemaStmtAttr.cpp |  9 +++++++--
 clang/lib/Sema/TreeTransform.h  |  2 ++
 clang/test/Sema/code_align.c    | 20 +++++++++++---------
 4 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index c291572ee0349b4..8a4fe2cc6dbe04f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2100,6 +2100,7 @@ class Sema final {
                                  SourceLocation AttrLoc);
 
   CodeAlignAttr *BuildCodeAlignAttr(const AttributeCommonInfo &CI, Expr *E);
+  bool CheckRebuiltCodeAlignStmtAttributes(ArrayRef<const Attr *> Attrs);
 
   bool CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc);
 
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index e6dedd650a3cc77..55da8387e549728 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -355,12 +355,12 @@ static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
   return S.BuildCodeAlignAttr(A, E);
 }
 
-// Diagnose non-identical duplicates as a 'conflicting' loop attr
+// Diagnose non-identical duplicates as a 'conflicting' loop attributes
 // and suppress duplicate errors in cases where the two match for
 // [[clang::code_align()]] attribute.
 static void
 CheckForDuplicateCodeAlignAttrs(Sema &S,
-                                const SmallVectorImpl<const Attr *> &Attrs) {
+                                ArrayRef<const Attr *> Attrs) {
   auto FindFunc = [](const Attr *A) { return isa<const CodeAlignAttr>(A); };
   const auto *FirstItr = std::find_if(Attrs.begin(), Attrs.end(), FindFunc);
 
@@ -621,3 +621,8 @@ void Sema::ProcessStmtAttributes(Stmt *S, const ParsedAttributes &InAttrs,
   CheckForIncompatibleAttributes(*this, OutAttrs);
   CheckForDuplicateCodeAlignAttrs(*this, OutAttrs);
 }
+
+bool Sema::CheckRebuiltCodeAlignStmtAttributes(ArrayRef<const Attr *> Attrs) {
+  CheckForDuplicateCodeAlignAttrs(*this, Attrs);
+  return false;
+}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index e24f710fdedd4e2..645a4988f26d34c 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1378,6 +1378,8 @@ class TreeTransform {
   StmtResult RebuildAttributedStmt(SourceLocation AttrLoc,
                                    ArrayRef<const Attr *> Attrs,
                                    Stmt *SubStmt) {
+    if (SemaRef.CheckRebuiltCodeAlignStmtAttributes(Attrs))
+      return StmtError();
     return SemaRef.BuildAttributedStmt(AttrLoc, Attrs, SubStmt);
   }
 
diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c
index 4234b8da380fb9f..539c0c0b0f1ccfb 100644
--- a/clang/test/Sema/code_align.c
+++ b/clang/test/Sema/code_align.c
@@ -127,8 +127,8 @@ void code_align_dependent() {
   [[clang::code_align(A)]] // OK
   for(int I=0; I<128; ++I) { bar(I); }
 
-  [[clang::code_align(A)]]
-  [[clang::code_align(E)]]
+  [[clang::code_align(A)]] // expected-note{{previous attribute is here}}
+  [[clang::code_align(E)]] // cpp-local-error{{conflicting loop attribute 'code_align'}}
   for(int I=0; I<128; ++I) { bar(I); }
 
   // cpp-local-error at +1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was 23}}
@@ -136,29 +136,31 @@ void code_align_dependent() {
   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; provided argument was -10}}
-  // cpp-local-note@#neg-instantiation{{in instantiation of function template specialization}}
+  // cpp-local-note@#neg-instantiation{{in instantiation of function template specialization 'code_align_dependent<8, 23, 32, -10, 64>' requested here}}
   [[clang::code_align(D)]]
   for(int I=0; I<128; ++I) { bar(I); }
 }
 
 template<int ITMPL>
 void bar3() {
-  [[clang::code_align(8)]]
-  [[clang::code_align(ITMPL)]]
+  [[clang::code_align(8)]]      // expected-note{{previous attribute is here}}
+  [[clang::code_align(ITMPL)]] // cpp-local-error{{conflicting loop attribute 'code_align'}} \
+	                       // cpp-local-note@#temp-instantiation{{in instantiation of function template specialization 'bar3<4>' requested here}}
   for(int I=0; I<128; ++I) { bar(I); }
 }
 
 template<int ITMPL1>
 void bar4() {
-  [[clang::code_align(ITMPL1)]]
-  [[clang::code_align(32)]]
+  [[clang::code_align(ITMPL1)]] // expected-note{{previous attribute is here}}
+  [[clang::code_align(32)]]    // cpp-local-error{{conflicting loop attribute 'code_align'}} \
+	                       // cpp-local-note@#temp-instantiation1{{in instantiation of function template specialization 'bar4<64>' requested here}}
   for(int I=0; I<128; ++I) { bar(I); }
 }
 
 int main() {
   code_align_dependent<8, 23, 32, -10, 64>(); // #neg-instantiation
-  bar3 <4>();
-  bar4 <64>();
+  bar3<4>();  // #temp-instantiation
+  bar4<64>(); // #temp-instantiation1
   return 0;
 }
 #endif

>From 886c03a23b334b4e46245a2087783238fc803c78 Mon Sep 17 00:00:00 2001
From: "Manna, Soumi" <soumi.manna at intel.com>
Date: Mon, 20 Nov 2023 10:17:50 -0800
Subject: [PATCH 39/39] Fix clang format errors

---
 clang/lib/Sema/SemaStmtAttr.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 55da8387e549728..eae1eaa2f9563d5 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -358,9 +358,8 @@ static Attr *handleCodeAlignAttr(Sema &S, Stmt *St, const ParsedAttr &A) {
 // Diagnose non-identical duplicates as a 'conflicting' loop attributes
 // and suppress duplicate errors in cases where the two match for
 // [[clang::code_align()]] attribute.
-static void
-CheckForDuplicateCodeAlignAttrs(Sema &S,
-                                ArrayRef<const Attr *> Attrs) {
+static void CheckForDuplicateCodeAlignAttrs(Sema &S,
+                                            ArrayRef<const Attr *> Attrs) {
   auto FindFunc = [](const Attr *A) { return isa<const CodeAlignAttr>(A); };
   const auto *FirstItr = std::find_if(Attrs.begin(), Attrs.end(), FindFunc);
 



More information about the llvm-commits mailing list