Skip to content

Commit 5e28af0

Browse files
authored
[C] Fix parsing of [[clang::assume]] (#141747)
The assumption attribute is exposed with a Clang spelling, which means we support __attribute__((assume)) as well as [[clang::assume]] as spellings for the attribute. In C++, the [[clang::assume]] spelling worked as expected. In C, that spelling would emit an "unknown attribute ignored" diagnostic. This was happening because we were failing to pass in the scope name and source location when creating the attribute. In C++, this worked by chance because [[assume]] is a known attribute in C++. But in C, where there is thankfully no [[assume]] standard attribute, the lack of a scope meant we would set the attribute kind to "unknown".
1 parent 2b1ebef commit 5e28af0

File tree

5 files changed

+45
-15
lines changed

5 files changed

+45
-15
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ C Language Changes
226226
- Added the existing ``-Wduplicate-decl-specifier`` diagnostic, which is on by
227227
default, to ``-Wc++-compat`` because duplicated declaration specifiers are
228228
not valid in C++.
229+
- The ``[[clang::assume()]]`` attribute is now correctly recognized in C. The
230+
``__attribute__((assume()))`` form has always been supported, so the fix is
231+
specific to the attribute syntax used.
229232

230233
C2y Feature Support
231234
^^^^^^^^^^^^^^^^^^^

clang/include/clang/Parse/Parser.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3037,11 +3037,11 @@ class Parser : public CodeCompletionHandler {
30373037

30383038
/// Parse the argument to C++23's [[assume()]] attribute. Returns true on
30393039
/// error.
3040-
bool ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs,
3041-
IdentifierInfo *AttrName,
3042-
SourceLocation AttrNameLoc,
3043-
SourceLocation *EndLoc,
3044-
ParsedAttr::Form Form);
3040+
bool
3041+
ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs, IdentifierInfo *AttrName,
3042+
SourceLocation AttrNameLoc,
3043+
IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
3044+
SourceLocation *EndLoc, ParsedAttr::Form Form);
30453045

30463046
/// Try to parse an 'identifier' which appears within an attribute-token.
30473047
///

clang/lib/Parse/ParseDecl.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,8 @@ void Parser::ParseGNUAttributeArgs(
676676
Form);
677677
return;
678678
} else if (AttrKind == ParsedAttr::AT_CXXAssume) {
679-
ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form);
679+
ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, ScopeName,
680+
ScopeLoc, EndLoc, Form);
680681
return;
681682
}
682683

@@ -734,7 +735,8 @@ unsigned Parser::ParseClangAttributeArgs(
734735
break;
735736

736737
case ParsedAttr::AT_CXXAssume:
737-
ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form);
738+
ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, ScopeName,
739+
ScopeLoc, EndLoc, Form);
738740
break;
739741
}
740742
return !Attrs.empty() ? Attrs.begin()->getNumArgs() : 0;

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4452,11 +4452,10 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
44524452
}
44534453
}
44544454

4455-
bool Parser::ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs,
4456-
IdentifierInfo *AttrName,
4457-
SourceLocation AttrNameLoc,
4458-
SourceLocation *EndLoc,
4459-
ParsedAttr::Form Form) {
4455+
bool Parser::ParseCXXAssumeAttributeArg(
4456+
ParsedAttributes &Attrs, IdentifierInfo *AttrName,
4457+
SourceLocation AttrNameLoc, IdentifierInfo *ScopeName,
4458+
SourceLocation ScopeLoc, SourceLocation *EndLoc, ParsedAttr::Form Form) {
44604459
assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");
44614460
BalancedDelimiterTracker T(*this, tok::l_paren);
44624461
T.consumeOpen();
@@ -4498,8 +4497,8 @@ bool Parser::ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs,
44984497
ArgsUnion Assumption = Res.get();
44994498
auto RParen = Tok.getLocation();
45004499
T.consumeClose();
4501-
Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), nullptr,
4502-
SourceLocation(), &Assumption, 1, Form);
4500+
Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), ScopeName, ScopeLoc,
4501+
&Assumption, 1, Form);
45034502

45044503
if (EndLoc)
45054504
*EndLoc = RParen;
@@ -4565,7 +4564,8 @@ bool Parser::ParseCXX11AttributeArgs(
45654564
ScopeName, ScopeLoc, Form);
45664565
// So does C++23's assume() attribute.
45674566
else if (!ScopeName && AttrName->isStr("assume")) {
4568-
if (ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form))
4567+
if (ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, nullptr,
4568+
SourceLocation{}, EndLoc, Form))
45694569
return true;
45704570
NumArgs = 1;
45714571
} else

clang/test/Sema/assume.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %clang_cc1 -std=c23 %s -verify
2+
3+
// Validate that the attribute works in C.
4+
static_assert(!__has_c_attribute(assume));
5+
static_assert(__has_c_attribute(clang::assume));
6+
static_assert(__has_attribute(assume));
7+
8+
void test(int n) {
9+
// Smoke test.
10+
__attribute__((assume(true)));
11+
[[clang::assume(true)]];
12+
13+
// Test diagnostics
14+
__attribute__((assume)); // expected-error {{'assume' attribute takes one argument}}
15+
__attribute__((assume())); // expected-error {{expected expression}}
16+
[[clang::assume]]; // expected-error {{'assume' attribute takes one argument}}
17+
[[clang::assume()]]; // expected-error {{expected expression}}
18+
19+
__attribute__((assume(n++))); // expected-warning {{assumption is ignored because it contains (potential) side-effects}}
20+
[[clang::assume(n++)]]; // expected-warning {{assumption is ignored because it contains (potential) side-effects}}
21+
22+
[[clang::assume(true)]] int x; // expected-error {{'assume' attribute cannot be applied to a declaration}}
23+
__attribute__((assume(true))) int y; // expected-error {{'assume' attribute cannot be applied to a declaration}}
24+
}
25+

0 commit comments

Comments
 (0)