[clang] a0d05ed - Handle interactions between reserved identifier and user-defined suffixes
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 23 06:38:54 PDT 2021
Author: serge-sans-paille
Date: 2021-06-23T15:38:42+02:00
New Revision: a0d05ed848990c06c6dcdfc2e37bc8f13f7fe470
URL: https://github.com/llvm/llvm-project/commit/a0d05ed848990c06c6dcdfc2e37bc8f13f7fe470
DIFF: https://github.com/llvm/llvm-project/commit/a0d05ed848990c06c6dcdfc2e37bc8f13f7fe470.diff
LOG: 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
Added:
Modified:
clang/include/clang/Sema/Sema.h
clang/lib/AST/Decl.cpp
clang/lib/Parse/ParseExprCXX.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/test/Sema/reserved-identifier.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index db389922ae3a1..5a9ed8519e765 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4122,7 +4122,8 @@ class Sema final {
bool RValueThis, unsigned ThisQuals);
CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
- bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id);
+ bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id,
+ bool IsUDSuffix);
LiteralOperatorLookupResult
LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef<QualType> ArgTys,
bool AllowRaw, bool AllowTemplate,
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 0fbe8ec161910..5047dc19b0c6f 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1081,10 +1081,9 @@ bool NamedDecl::isLinkageValid() const {
ReservedIdentifierStatus
NamedDecl::isReserved(const LangOptions &LangOpts) const {
const IdentifierInfo *II = getIdentifier();
- if (!II)
- if (const auto *FD = dyn_cast<FunctionDecl>(this))
- II = FD->getLiteralIdentifier();
+ // This triggers at least for CXXLiteralIdentifiers, which we already checked
+ // at lexing time.
if (!II)
return ReservedIdentifierStatus::NotReserved;
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 93f578edc09e6..f3d10b4a08895 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -9,7 +9,6 @@
// This file implements the Expression parsing implementation for C++.
//
//===----------------------------------------------------------------------===//
-#include "clang/Parse/Parser.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
@@ -17,6 +16,7 @@
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
@@ -2636,9 +2636,10 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
// Grab the literal operator's suffix, which will be either the next token
// or a ud-suffix from the string literal.
+ bool IsUDSuffix = !Literal.getUDSuffix().empty();
IdentifierInfo *II = nullptr;
SourceLocation SuffixLoc;
- if (!Literal.getUDSuffix().empty()) {
+ if (IsUDSuffix) {
II = &PP.getIdentifierTable().get(Literal.getUDSuffix());
SuffixLoc =
Lexer::AdvanceToTokenCharacter(TokLocs[Literal.getUDSuffixToken()],
@@ -2675,7 +2676,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
Result.setLiteralOperatorId(II, KeywordLoc, SuffixLoc);
- return Actions.checkLiteralOperatorId(SS, Result);
+ return Actions.checkLiteralOperatorId(SS, Result, IsUDSuffix);
}
// Parse a conversion-function-id.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index a57c5ad198e1b..b0b6b3dca5f6a 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -484,8 +484,25 @@ ParsedType Sema::getDestructorTypeForDecltype(const DeclSpec &DS,
}
bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
- const UnqualifiedId &Name) {
+ const UnqualifiedId &Name, bool IsUDSuffix) {
assert(Name.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId);
+ if (!IsUDSuffix) {
+ // [over.literal] p8
+ //
+ // double operator""_Bq(long double); // OK: not a reserved identifier
+ // double operator"" _Bq(long double); // ill-formed, no diagnostic required
+ IdentifierInfo *II = Name.Identifier;
+ ReservedIdentifierStatus Status = II->isReserved(PP.getLangOpts());
+ SourceLocation Loc = Name.getEndLoc();
+ if (Status != ReservedIdentifierStatus::NotReserved &&
+ !PP.getSourceManager().isInSystemHeader(Loc)) {
+ Diag(Loc, diag::warn_reserved_extern_symbol)
+ << II << static_cast<int>(Status)
+ << FixItHint::CreateReplacement(
+ Name.getSourceRange(),
+ (StringRef("operator\"\"") + II->getName()).str());
+ }
+ }
if (!SS.isValid())
return false;
diff --git a/clang/test/Sema/reserved-identifier.cpp b/clang/test/Sema/reserved-identifier.cpp
index 1992f6976c38f..1d3e0f9f0043f 100644
--- a/clang/test/Sema/reserved-identifier.cpp
+++ b/clang/test/Sema/reserved-identifier.cpp
@@ -76,11 +76,19 @@ namespace {
int _barbatruc; // no-warning
}
-long double operator"" _BarbeBleue(long double) // expected-warning {{identifier 'operator""_BarbeBleue' is reserved because it starts with '_' followed by a capital letter}}
+long double operator"" _BarbeBleue(long double) // expected-warning {{identifier '_BarbeBleue' is reserved because it starts with '_' followed by a capital letter}}
{
return 0.;
}
+long double operator""_SacreBleu(long double) // no-warning
+{
+ return 0.;
+}
+
+long double sacrebleu = operator"" _SacreBleu(1.2); // expected-warning {{identifier '_SacreBleu' is reserved because it starts with '_' followed by a capital letter}}
+long double sangbleu = operator""_SacreBleu(1.2); // no-warning
+
struct _BarbeRouge { // expected-warning {{identifier '_BarbeRouge' is reserved because it starts with '_' followed by a capital letter}}
} p;
struct _BarbeNoire { // expected-warning {{identifier '_BarbeNoire' is reserved because it starts with '_' followed by a capital letter}}
More information about the cfe-commits
mailing list