Skip to content

Commit 46f3ade

Browse files
giulianobelinassierichkeane
authored andcommitted
Fix ast print of variables with attributes
Previously clang AST prints the following declaration: int fun_var_unused() { int x __attribute__((unused)) = 0; return x; } and int __declspec(thread) x = 0; as: int fun_var_unused() { int x = 0 __attribute__((unused)); return x; } and int x = __declspec(thread) 0; which is rejected by C/C++ parser. This patch modifies the logic to print old C attributes for variables as: int __attribute__((unused)) x = 0; and the __declspec case as: int __declspec(thread) x = 0; Fixes: #59973 Previous version: D141714. Differential Revision:https://reviews.llvm.org/D141714
1 parent 04224d1 commit 46f3ade

18 files changed

+243
-55
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,13 @@ class Spelling<string name, string variety, int version = 1> {
300300
}
301301

302302
class GNU<string name> : Spelling<name, "GNU">;
303-
class Declspec<string name> : Spelling<name, "Declspec">;
303+
class Declspec<string name> : Spelling<name, "Declspec"> {
304+
bit PrintOnLeft = 1;
305+
}
304306
class Microsoft<string name> : Spelling<name, "Microsoft">;
305307
class CXX11<string namespace, string name, int version = 1>
306308
: Spelling<name, "CXX11", version> {
309+
bit CanPrintOnLeft = 0;
307310
string Namespace = namespace;
308311
}
309312
class C23<string namespace, string name, int version = 1>
@@ -559,6 +562,12 @@ class AttrSubjectMatcherAggregateRule<AttrSubject subject> {
559562
def SubjectMatcherForNamed : AttrSubjectMatcherAggregateRule<Named>;
560563

561564
class Attr {
565+
// Specifies that when printed, this attribute is meaningful on the
566+
// 'left side' of the declaration.
567+
bit CanPrintOnLeft = 1;
568+
// Specifies that when printed, this attribute is required to be printed on
569+
// the 'left side' of the declaration.
570+
bit PrintOnLeft = 0;
562571
// The various ways in which an attribute can be spelled in source
563572
list<Spelling> Spellings;
564573
// The things to which an attribute can appertain
@@ -892,6 +901,7 @@ def AVRSignal : InheritableAttr, TargetSpecificAttr<TargetAVR> {
892901
}
893902

894903
def AsmLabel : InheritableAttr {
904+
let CanPrintOnLeft = 0;
895905
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
896906
let Args = [
897907
// Label specifies the mangled name for the decl.
@@ -1434,6 +1444,7 @@ def AllocSize : InheritableAttr {
14341444
}
14351445

14361446
def EnableIf : InheritableAttr {
1447+
let CanPrintOnLeft = 0;
14371448
// Does not have a [[]] spelling because this attribute requires the ability
14381449
// to parse function arguments but the attribute is not written in the type
14391450
// position.
@@ -2920,6 +2931,7 @@ def Unavailable : InheritableAttr {
29202931
}
29212932

29222933
def DiagnoseIf : InheritableAttr {
2934+
let CanPrintOnLeft = 0;
29232935
// Does not have a [[]] spelling because this attribute requires the ability
29242936
// to parse function arguments but the attribute is not written in the type
29252937
// position.

clang/include/clang/Basic/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ clang_tablegen(AttrList.inc -gen-clang-attr-list
3030
SOURCE Attr.td
3131
TARGET ClangAttrList)
3232

33+
clang_tablegen(AttrLeftSideCanPrintList.inc -gen-clang-attr-can-print-left-list
34+
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
35+
SOURCE Attr.td
36+
TARGET ClangAttrCanPrintLeftList)
37+
38+
clang_tablegen(AttrLeftSideMustPrintList.inc -gen-clang-attr-must-print-left-list
39+
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
40+
SOURCE Attr.td
41+
TARGET ClangAttrMustPrintLeftList)
42+
3343
clang_tablegen(AttrSubMatchRulesList.inc -gen-clang-attr-subject-match-rule-list
3444
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
3545
SOURCE Attr.td

clang/lib/AST/DeclPrinter.cpp

Lines changed: 123 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,18 @@ namespace {
4949

5050
void PrintObjCTypeParams(ObjCTypeParamList *Params);
5151

52+
enum class AttrPrintLoc {
53+
None = 0,
54+
Left = 1,
55+
Right = 2,
56+
Any = Left | Right,
57+
58+
LLVM_MARK_AS_BITMASK_ENUM(/*DefaultValue=*/Any)
59+
};
60+
61+
void prettyPrintAttributes(Decl *D, raw_ostream &out,
62+
AttrPrintLoc loc = AttrPrintLoc::Any);
63+
5264
public:
5365
DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
5466
const ASTContext &Context, unsigned Indentation = 0,
@@ -117,7 +129,11 @@ namespace {
117129
const TemplateParameterList *Params);
118130
void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
119131
const TemplateParameterList *Params);
120-
void prettyPrintAttributes(Decl *D);
132+
133+
inline void prettyPrintAttributes(Decl *D) {
134+
prettyPrintAttributes(D, Out);
135+
}
136+
121137
void prettyPrintPragmas(Decl *D);
122138
void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
123139
};
@@ -234,7 +250,40 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
234250
return Out;
235251
}
236252

237-
void DeclPrinter::prettyPrintAttributes(Decl *D) {
253+
static bool canPrintOnLeftSide(attr::Kind kind) {
254+
switch (kind) {
255+
#include "clang/Basic/AttrLeftSideCanPrintList.inc"
256+
return true;
257+
default:
258+
return false;
259+
}
260+
}
261+
262+
static bool canPrintOnLeftSide(const Attr *A) {
263+
if (A->isStandardAttributeSyntax())
264+
return false;
265+
266+
return canPrintOnLeftSide(A->getKind());
267+
}
268+
269+
static bool mustPrintOnLeftSide(attr::Kind kind) {
270+
switch (kind) {
271+
#include "clang/Basic/AttrLeftSideMustPrintList.inc"
272+
return true;
273+
default:
274+
return false;
275+
}
276+
}
277+
278+
static bool mustPrintOnLeftSide(const Attr *A) {
279+
if (A->isDeclspecAttribute())
280+
return true;
281+
282+
return mustPrintOnLeftSide(A->getKind());
283+
}
284+
285+
void DeclPrinter::prettyPrintAttributes(Decl *D, llvm::raw_ostream &Out,
286+
AttrPrintLoc Loc) {
238287
if (Policy.PolishForDeclaration)
239288
return;
240289

@@ -243,15 +292,32 @@ void DeclPrinter::prettyPrintAttributes(Decl *D) {
243292
for (auto *A : Attrs) {
244293
if (A->isInherited() || A->isImplicit())
245294
continue;
246-
switch (A->getKind()) {
247-
#define ATTR(X)
248-
#define PRAGMA_SPELLING_ATTR(X) case attr::X:
249-
#include "clang/Basic/AttrList.inc"
250-
break;
251-
default:
252-
A->printPretty(Out, Policy);
253-
break;
295+
296+
AttrPrintLoc AttrLoc = AttrPrintLoc::Right;
297+
if (mustPrintOnLeftSide(A)) {
298+
// If we must always print on left side (e.g. declspec), then mark as
299+
// so.
300+
AttrLoc = AttrPrintLoc::Left;
301+
} else if (canPrintOnLeftSide(A)) {
302+
// For functions with body defined we print the attributes on the left
303+
// side so that GCC accept our dumps as well.
304+
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
305+
FD && FD->isThisDeclarationADefinition())
306+
// In case Decl is a function with a body, then attrs should be print
307+
// on the left side.
308+
AttrLoc = AttrPrintLoc::Left;
309+
310+
// In case it is a variable declaration with a ctor, then allow
311+
// printing on the left side for readbility.
312+
else if (const VarDecl *VD = dyn_cast<VarDecl>(D);
313+
VD && VD->getInit() &&
314+
VD->getInitStyle() == VarDecl::CallInit)
315+
AttrLoc = AttrPrintLoc::Left;
254316
}
317+
318+
// Only print the side matches the user requested.
319+
if ((Loc & AttrLoc) != AttrPrintLoc::None)
320+
A->printPretty(Out, Policy);
255321
}
256322
}
257323
}
@@ -613,6 +679,22 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
613679
printTemplateParameters(D->getTemplateParameterList(I));
614680
}
615681

682+
std::string LeftsideAttrs;
683+
llvm::raw_string_ostream LSAS(LeftsideAttrs);
684+
685+
prettyPrintAttributes(D, LSAS, AttrPrintLoc::Left);
686+
687+
// prettyPrintAttributes print a space on left side of the attribute.
688+
if (LeftsideAttrs[0] == ' ') {
689+
// Skip the space prettyPrintAttributes generated.
690+
LeftsideAttrs.erase(0, LeftsideAttrs.find_first_not_of(' '));
691+
692+
// Add a single space between the attribute and the Decl name.
693+
LSAS << ' ';
694+
}
695+
696+
Out << LeftsideAttrs;
697+
616698
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
617699
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
618700
CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D);
@@ -774,7 +856,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
774856
Ty.print(Out, Policy, Proto);
775857
}
776858

777-
prettyPrintAttributes(D);
859+
prettyPrintAttributes(D, Out, AttrPrintLoc::Right);
778860

779861
if (D->isPure())
780862
Out << " = 0";
@@ -867,6 +949,23 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
867949
void DeclPrinter::VisitVarDecl(VarDecl *D) {
868950
prettyPrintPragmas(D);
869951

952+
std::string LeftSide;
953+
llvm::raw_string_ostream LeftSideStream(LeftSide);
954+
955+
// Print attributes that should be placed on the left, such as __declspec.
956+
prettyPrintAttributes(D, LeftSideStream, AttrPrintLoc::Left);
957+
958+
// prettyPrintAttributes print a space on left side of the attribute.
959+
if (LeftSide[0] == ' ') {
960+
// Skip the space prettyPrintAttributes generated.
961+
LeftSide.erase(0, LeftSide.find_first_not_of(' '));
962+
963+
// Add a single space between the attribute and the Decl name.
964+
LeftSideStream << ' ';
965+
}
966+
967+
Out << LeftSide;
968+
870969
QualType T = D->getTypeSourceInfo()
871970
? D->getTypeSourceInfo()->getType()
872971
: D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
@@ -899,10 +998,19 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
899998
}
900999
}
9011000

902-
printDeclType(T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
903-
D->getIdentifier())
904-
? D->getIdentifier()->deuglifiedName()
905-
: D->getName());
1001+
StringRef Name;
1002+
1003+
Name = (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
1004+
D->getIdentifier())
1005+
? D->getIdentifier()->deuglifiedName()
1006+
: D->getName();
1007+
1008+
printDeclType(T, Name);
1009+
1010+
// Print the attributes that should be placed right before the end of the
1011+
// decl.
1012+
prettyPrintAttributes(D, Out, AttrPrintLoc::Right);
1013+
9061014
Expr *Init = D->getInit();
9071015
if (!Policy.SuppressInitializers && Init) {
9081016
bool ImplicitInit = false;
@@ -931,7 +1039,6 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
9311039
Out << ")";
9321040
}
9331041
}
934-
prettyPrintAttributes(D);
9351042
}
9361043

9371044
void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {

clang/test/AST/ast-print-attr-knr.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// This file contain tests for attribute arguments on K&R functions.
2+
3+
// RUN: %clang_cc1 -ast-print -x c -std=c89 -fms-extensions %s -o - | FileCheck %s
4+
5+
// CHECK: int knr(i)
6+
// CHECK-NEXT: int i __attribute__((unused));
7+
// CHECK-NEXT: {
8+
// CHECK-NEXT: return 0;
9+
// CHECK-NEXT: }
10+
int knr(i) int i __attribute__((unused)); { return 0; }
11+
12+
// CHECK: __attribute__((unused)) int knr2(i)
13+
// CHECK-NEXT: int i;
14+
// CHECK-NEXT: {
15+
// CHECK-NEXT: return 0;
16+
// CHECK-NEXT: }
17+
__attribute__((unused)) int knr2(i) int i; { return 0; }

clang/test/AST/ast-print-attr.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,9 @@ int *fun_returns() __attribute__((ownership_returns(fun_returns)));
3232

3333
// CHECK: void fun_holds(int *a) __attribute__((ownership_holds(fun_holds, 1)));
3434
void fun_holds(int *a) __attribute__((ownership_holds(fun_holds, 1)));
35+
36+
// CHECK: int fun_var_unused() {
37+
// CHECK-NEXT: int x __attribute__((unused)) = 0;
38+
// CHECK-NEXT: return x;
39+
// CHECK-NEXT: }
40+
int fun_var_unused() { int x __attribute__((unused)) = 0; return x; }

clang/test/AST/ast-print-method-decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ struct DefMethodsWithoutBody {
9595
// CHECK-NEXT: DefMethodsWithoutBody() = default;
9696
~DefMethodsWithoutBody() = default;
9797

98-
// CHECK-NEXT: void m1() __attribute__((alias("X")));
98+
// CHECK-NEXT: __attribute__((alias("X"))) void m1();
9999
void m1() __attribute__((alias("X")));
100100

101101
// CHECK-NEXT: };

clang/test/AST/ast-print-pragmas.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ void test_templates(int *List, int Length) {
9393
#ifdef MS_EXT
9494
#pragma init_seg(compiler)
9595
// MS-EXT: #pragma init_seg (.CRT$XCC){{$}}
96-
// MS-EXT-NEXT: int x = 3 __declspec(thread);
97-
int __declspec(thread) x = 3;
96+
// MS-EXT-NEXT: __declspec(thread) int x = 3;
97+
__declspec(thread) int x = 3;
9898
#endif //MS_EXT
9999

clang/test/Analysis/blocks.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ void testBlockWithCaptureByReference() {
7878
// CHECK-NEXT: 1: 5
7979
// WARNINGS-NEXT: 2: [B1.1] (CXXConstructExpr, StructWithCopyConstructor)
8080
// ANALYZER-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.3], StructWithCopyConstructor)
81-
// CHECK-NEXT: 3: StructWithCopyConstructor s(5) __attribute__((blocks("byref")));
81+
// CHECK-NEXT: 3: __attribute__((blocks("byref"))) StructWithCopyConstructor s(5);
8282
// CHECK-NEXT: 4: ^{ }
8383
// CHECK-NEXT: 5: (void)([B1.4]) (CStyleCastExpr, ToVoid, void)
8484
// CHECK-NEXT: Preds (1): B2

clang/test/OpenMP/assumes_codegen.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,41 +67,41 @@ int lambda_outer() {
6767
}
6868
#pragma omp end assumes
6969

70-
// AST: void foo() __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
70+
// AST: __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void foo() {
7171
// AST-NEXT: }
7272
// AST-NEXT: class BAR {
7373
// AST-NEXT: public:
74-
// AST-NEXT: BAR() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
74+
// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAR() {
7575
// AST-NEXT: }
76-
// AST-NEXT: void bar1() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
76+
// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void bar1() {
7777
// AST-NEXT: }
78-
// AST-NEXT: static void bar2() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
78+
// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) static void bar2() {
7979
// AST-NEXT: }
8080
// AST-NEXT: };
81-
// AST-NEXT: void bar() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
81+
// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void bar() {
8282
// AST-NEXT: BAR b;
8383
// AST-NEXT: }
8484
// AST-NEXT: void baz() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp")));
8585
// AST-NEXT: template <typename T> class BAZ {
8686
// AST-NEXT: public:
87-
// AST-NEXT: BAZ<T>() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
87+
// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAZ<T>() {
8888
// AST-NEXT: }
89-
// AST-NEXT: void baz1() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
89+
// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz1() {
9090
// AST-NEXT: }
91-
// AST-NEXT: static void baz2() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
91+
// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) static void baz2() {
9292
// AST-NEXT: }
9393
// AST-NEXT: };
9494
// AST-NEXT: template<> class BAZ<float> {
9595
// AST-NEXT: public:
96-
// AST-NEXT: BAZ() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
96+
// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAZ() {
9797
// AST-NEXT: }
9898
// AST-NEXT: void baz1() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp")));
9999
// AST-NEXT: static void baz2() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp")));
100100
// AST-NEXT: };
101-
// AST-NEXT: void baz() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
101+
// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz() {
102102
// AST-NEXT: BAZ<float> b;
103103
// AST-NEXT: }
104-
// AST-NEXT: int lambda_outer() __attribute__((assume("ompx_lambda_assumption"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
104+
// AST-NEXT: __attribute__((assume("ompx_lambda_assumption"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) int lambda_outer() {
105105
// AST-NEXT: auto lambda_inner = []() {
106106
// AST-NEXT: return 42;
107107
// AST-NEXT: };

clang/test/OpenMP/assumes_print.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ void baz() {
3737
}
3838
#pragma omp end assumes
3939

40-
// CHECK: void foo() __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp")))
41-
// CHECK: void bar() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp")))
42-
// CHECK: void baz() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp")))
40+
// CHECK: __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) void foo()
41+
// CHECK: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) void bar()
42+
// CHECK: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) void baz()
4343

4444
#endif

0 commit comments

Comments
 (0)