diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -3099,7 +3099,7 @@ Token LoopHintTok; LoopHintTok.startToken(); LoopHintTok.setKind(tok::annot_pragma_loop_hint); - LoopHintTok.setLocation(PragmaName.getLocation()); + LoopHintTok.setLocation(Introducer.Loc); LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation()); LoopHintTok.setAnnotationValue(static_cast(Info)); TokenList.push_back(LoopHintTok); @@ -3186,7 +3186,7 @@ auto TokenArray = std::make_unique(1); TokenArray[0].startToken(); TokenArray[0].setKind(tok::annot_pragma_loop_hint); - TokenArray[0].setLocation(PragmaName.getLocation()); + TokenArray[0].setLocation(Introducer.Loc); TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation()); TokenArray[0].setAnnotationValue(static_cast(Info)); PP.EnterTokenStream(std::move(TokenArray), 1, diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -2172,6 +2172,8 @@ // Create temporary attribute list. ParsedAttributesWithRange TempAttrs(AttrFactory); + SourceLocation StartLoc = Tok.getLocation(); + // Get loop hints and consume annotated token. while (Tok.is(tok::annot_pragma_loop_hint)) { LoopHint Hint; @@ -2192,6 +2194,10 @@ Stmts, StmtCtx, TrailingElseLoc, Attrs); Attrs.takeAllFrom(TempAttrs); + + assert(Attrs.Range.getBegin().isInvalid() && + "start of attribute range already set"); + Attrs.Range.setBegin(StartLoc); return S; } diff --git a/clang/test/AST/sourceranges.cpp b/clang/test/AST/sourceranges.cpp --- a/clang/test/AST/sourceranges.cpp +++ b/clang/test/AST/sourceranges.cpp @@ -108,6 +108,36 @@ } } +// CHECK: NamespaceDecl {{.*}} attributed_stmt +namespace attributed_stmt { + // In DO_PRAGMA and _Pragma cases, `LoopHintAttr` comes from + // file. + + #define DO_PRAGMA(x) _Pragma (#x) + + void f() { + // CHECK: AttributedStmt {{.*}} + DO_PRAGMA (unroll(2)) + for (int i = 0; i < 10; ++i); + + // CHECK: AttributedStmt {{.*}} + // CHECK: LoopHintAttr {{.*}} + #pragma unroll(2) + for (int i = 0; i < 10; ++i); + + // CHECK: AttributedStmt {{.*}} + // CHECK: LoopHintAttr {{.*}} + #pragma clang loop vectorize(enable) + // CHECK: LoopHintAttr {{.*}} + #pragma clang loop interleave(enable) + for (int i = 0; i < 10; ++i); + + // CHECK: AttributedStmt {{.*}} + _Pragma("unroll(2)") + for (int i = 0; i < 10; ++i); + } +} + #if __cplusplus >= 201703L // CHECK-1Z: FunctionDecl {{.*}} construct_with_init_list std::map construct_with_init_list() {