Skip to content

Commit a0d05ed

Browse files
author
serge-sans-paille
committed
Handle interactions between reserved identifier and user-defined suffixes
According to https://eel.is/c++draft/over.literal > double operator""_Bq(long double); // OK: does not use the reserved identifier _­Bq ([lex.name]) > double operator"" _Bq(long double); // ill-formed, no diagnostic required: uses the reserved identifier _­Bq ([lex.name]) Obey that rule by keeping track of the operator literal name status wrt. leading whitespace. Fix: https://bugs.llvm.org/show_bug.cgi?id=50644 Differential Revision: https://reviews.llvm.org/D104299
1 parent a16cb95 commit a0d05ed

File tree

5 files changed

+35
-9
lines changed

5 files changed

+35
-9
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4122,7 +4122,8 @@ class Sema final {
41224122
bool RValueThis, unsigned ThisQuals);
41234123
CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
41244124

4125-
bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id);
4125+
bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id,
4126+
bool IsUDSuffix);
41264127
LiteralOperatorLookupResult
41274128
LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef<QualType> ArgTys,
41284129
bool AllowRaw, bool AllowTemplate,

clang/lib/AST/Decl.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,10 +1081,9 @@ bool NamedDecl::isLinkageValid() const {
10811081
ReservedIdentifierStatus
10821082
NamedDecl::isReserved(const LangOptions &LangOpts) const {
10831083
const IdentifierInfo *II = getIdentifier();
1084-
if (!II)
1085-
if (const auto *FD = dyn_cast<FunctionDecl>(this))
1086-
II = FD->getLiteralIdentifier();
10871084

1085+
// This triggers at least for CXXLiteralIdentifiers, which we already checked
1086+
// at lexing time.
10881087
if (!II)
10891088
return ReservedIdentifierStatus::NotReserved;
10901089

clang/lib/Parse/ParseExprCXX.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
// This file implements the Expression parsing implementation for C++.
1010
//
1111
//===----------------------------------------------------------------------===//
12-
#include "clang/Parse/Parser.h"
1312
#include "clang/AST/ASTContext.h"
1413
#include "clang/AST/Decl.h"
1514
#include "clang/AST/DeclTemplate.h"
1615
#include "clang/AST/ExprCXX.h"
1716
#include "clang/Basic/PrettyStackTrace.h"
1817
#include "clang/Lex/LiteralSupport.h"
1918
#include "clang/Parse/ParseDiagnostic.h"
19+
#include "clang/Parse/Parser.h"
2020
#include "clang/Parse/RAIIObjectsForParser.h"
2121
#include "clang/Sema/DeclSpec.h"
2222
#include "clang/Sema/ParsedTemplate.h"
@@ -2636,9 +2636,10 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
26362636

26372637
// Grab the literal operator's suffix, which will be either the next token
26382638
// or a ud-suffix from the string literal.
2639+
bool IsUDSuffix = !Literal.getUDSuffix().empty();
26392640
IdentifierInfo *II = nullptr;
26402641
SourceLocation SuffixLoc;
2641-
if (!Literal.getUDSuffix().empty()) {
2642+
if (IsUDSuffix) {
26422643
II = &PP.getIdentifierTable().get(Literal.getUDSuffix());
26432644
SuffixLoc =
26442645
Lexer::AdvanceToTokenCharacter(TokLocs[Literal.getUDSuffixToken()],
@@ -2675,7 +2676,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
26752676

26762677
Result.setLiteralOperatorId(II, KeywordLoc, SuffixLoc);
26772678

2678-
return Actions.checkLiteralOperatorId(SS, Result);
2679+
return Actions.checkLiteralOperatorId(SS, Result, IsUDSuffix);
26792680
}
26802681

26812682
// Parse a conversion-function-id.

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,25 @@ ParsedType Sema::getDestructorTypeForDecltype(const DeclSpec &DS,
484484
}
485485

486486
bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
487-
const UnqualifiedId &Name) {
487+
const UnqualifiedId &Name, bool IsUDSuffix) {
488488
assert(Name.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId);
489+
if (!IsUDSuffix) {
490+
// [over.literal] p8
491+
//
492+
// double operator""_Bq(long double); // OK: not a reserved identifier
493+
// double operator"" _Bq(long double); // ill-formed, no diagnostic required
494+
IdentifierInfo *II = Name.Identifier;
495+
ReservedIdentifierStatus Status = II->isReserved(PP.getLangOpts());
496+
SourceLocation Loc = Name.getEndLoc();
497+
if (Status != ReservedIdentifierStatus::NotReserved &&
498+
!PP.getSourceManager().isInSystemHeader(Loc)) {
499+
Diag(Loc, diag::warn_reserved_extern_symbol)
500+
<< II << static_cast<int>(Status)
501+
<< FixItHint::CreateReplacement(
502+
Name.getSourceRange(),
503+
(StringRef("operator\"\"") + II->getName()).str());
504+
}
505+
}
489506

490507
if (!SS.isValid())
491508
return false;

clang/test/Sema/reserved-identifier.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,19 @@ namespace {
7676
int _barbatruc; // no-warning
7777
}
7878

79-
long double operator"" _BarbeBleue(long double) // expected-warning {{identifier 'operator""_BarbeBleue' is reserved because it starts with '_' followed by a capital letter}}
79+
long double operator"" _BarbeBleue(long double) // expected-warning {{identifier '_BarbeBleue' is reserved because it starts with '_' followed by a capital letter}}
8080
{
8181
return 0.;
8282
}
8383

84+
long double operator""_SacreBleu(long double) // no-warning
85+
{
86+
return 0.;
87+
}
88+
89+
long double sacrebleu = operator"" _SacreBleu(1.2); // expected-warning {{identifier '_SacreBleu' is reserved because it starts with '_' followed by a capital letter}}
90+
long double sangbleu = operator""_SacreBleu(1.2); // no-warning
91+
8492
struct _BarbeRouge { // expected-warning {{identifier '_BarbeRouge' is reserved because it starts with '_' followed by a capital letter}}
8593
} p;
8694
struct _BarbeNoire { // expected-warning {{identifier '_BarbeNoire' is reserved because it starts with '_' followed by a capital letter}}

0 commit comments

Comments
 (0)