[clang] b83b232 - Introduce -Wreserved-identifier
via cfe-commits
cfe-commits at lists.llvm.org
Tue May 4 02:20:40 PDT 2021
Author: serge-sans-paille
Date: 2021-05-04T11:19:01+02:00
New Revision: b83b23275b745287bf9d3d72a93b593119f53f75
URL: https://github.com/llvm/llvm-project/commit/b83b23275b745287bf9d3d72a93b593119f53f75
DIFF: https://github.com/llvm/llvm-project/commit/b83b23275b745287bf9d3d72a93b593119f53f75.diff
LOG: Introduce -Wreserved-identifier
Warn when a declaration uses an identifier that doesn't obey the reserved
identifier rule from C and/or C++.
Differential Revision: https://reviews.llvm.org/D93095
Added:
clang/test/Sema/reserved-identifier.c
clang/test/Sema/reserved-identifier.cpp
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/Decl.h
clang/include/clang/Basic/DiagnosticGroups.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/IdentifierTable.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/Decl.cpp
clang/lib/Basic/IdentifierTable.cpp
clang/lib/CodeGen/CGDebugInfo.cpp
clang/lib/Sema/SemaCodeComplete.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaStmt.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/test/Preprocessor/macro-reserved.c
clang/test/Preprocessor/macro-reserved.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 36ceb1bc7cfb5..bb8a28ed236ba 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -67,7 +67,8 @@ Non-comprehensive list of changes in this release
New Compiler Flags
------------------
-- ...
+- ``-Wreserved-identifier`` emits warning when user code uses reserved
+ identifiers.
Deprecated Compiler Flags
-------------------------
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 66dda5c9761ae..020df62755706 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -356,6 +356,10 @@ class NamedDecl : public Decl {
/// a C++ class.
bool isCXXInstanceMember() const;
+ /// Determine if the declaration obeys the reserved identifier rules of the
+ /// given language.
+ ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const;
+
/// Determine what kind of linkage this entity has.
///
/// This is not the linkage as defined by the standard or the codegen notion
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 3a7f18b60398b..f6a4fbb1e04c8 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -638,7 +638,8 @@ def : DiagGroup<"sequence-point", [Unsequenced]>;
// Preprocessor warnings.
def AmbiguousMacro : DiagGroup<"ambiguous-macro">;
def KeywordAsMacro : DiagGroup<"keyword-macro">;
-def ReservedIdAsMacro : DiagGroup<"reserved-id-macro">;
+def ReservedIdAsMacro : DiagGroup<"reserved-macro-identifier">;
+def ReservedIdAsMacroAlias : DiagGroup<"reserved-id-macro", [ReservedIdAsMacro]>;
// Just silence warnings about -Wstrict-aliasing for now.
def : DiagGroup<"strict-aliasing=0">;
@@ -801,6 +802,9 @@ def LargeByValueCopy : DiagGroup<"large-by-value-copy">;
def DuplicateArgDecl : DiagGroup<"duplicate-method-arg">;
def SignedEnumBitfield : DiagGroup<"signed-enum-bitfield">;
+def ReservedIdentifier : DiagGroup<"reserved-identifier",
+ [ReservedIdAsMacro]>;
+
// Unreachable code warning groups.
//
// The goal is make -Wunreachable-code on by default, in -Wall, or at
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 639565feb5766..c3ada2ccebab4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -379,6 +379,15 @@ def warn_unused_lambda_capture: Warning<"lambda capture %0 is not "
"%select{used|required to be captured for this use}1">,
InGroup<UnusedLambdaCapture>, DefaultIgnore;
+def warn_reserved_extern_symbol: Warning<
+ "identifier %0 is reserved because %select{"
+ "<ERROR>|" // ReservedIdentifierStatus::NotReserved
+ "it starts with '_' at global scope|"
+ "it starts with '__'|"
+ "it starts with '_' followed by a capital letter|"
+ "it contains '__'}1">,
+ InGroup<ReservedIdentifier>, DefaultIgnore;
+
def warn_parameter_size: Warning<
"%0 is a large (%1 bytes) pass-by-value argument; "
"pass it by reference instead ?">, InGroup<LargeByValueCopy>;
diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h
index 204a0f0cc0a5d..e074a7d3254cf 100644
--- a/clang/include/clang/Basic/IdentifierTable.h
+++ b/clang/include/clang/Basic/IdentifierTable.h
@@ -40,6 +40,14 @@ class LangOptions;
class MultiKeywordSelector;
class SourceLocation;
+enum class ReservedIdentifierStatus {
+ NotReserved = 0,
+ StartsWithUnderscoreAtGlobalScope,
+ StartsWithDoubleUnderscore,
+ StartsWithUnderscoreFollowedByCapitalLetter,
+ ContainsDoubleUnderscore,
+};
+
/// A simple pair of identifier info and location.
using IdentifierLocPair = std::pair<IdentifierInfo *, SourceLocation>;
@@ -385,14 +393,7 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
/// Determine whether \p this is a name reserved for the implementation (C99
/// 7.1.3, C++ [lib.global.names]).
- bool isReservedName(bool doubleUnderscoreOnly = false) const {
- if (getLength() < 2)
- return false;
- const char *Name = getNameStart();
- return Name[0] == '_' &&
- (Name[1] == '_' ||
- (Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly));
- }
+ ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const;
/// Provide less than operator for lexicographical sorting.
bool operator<(const IdentifierInfo &RHS) const {
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 44f97c0d949f7..95d586825304d 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2590,6 +2590,8 @@ class Sema final {
SourceLocation Less,
SourceLocation Greater);
+ void warnOnReservedIdentifier(const NamedDecl *D);
+
Decl *ActOnDeclarator(Scope *S, Declarator &D);
NamedDecl *HandleDeclarator(Scope *S, Declarator &D,
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index f77acefb17815..c5c8f473dda95 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1078,6 +1078,29 @@ bool NamedDecl::isLinkageValid() const {
return L == getCachedLinkage();
}
+ReservedIdentifierStatus
+NamedDecl::isReserved(const LangOptions &LangOpts) const {
+ const IdentifierInfo *II = getIdentifier();
+ if (!II)
+ if (const auto *FD = dyn_cast<FunctionDecl>(this))
+ II = FD->getLiteralIdentifier();
+
+ if (!II)
+ return ReservedIdentifierStatus::NotReserved;
+
+ ReservedIdentifierStatus Status = II->isReserved(LangOpts);
+ if (Status == ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope) {
+ // Check if we're at TU level or not.
+ if (isa<ParmVarDecl>(this) || isTemplateParameter())
+ return ReservedIdentifierStatus::NotReserved;
+ const DeclContext *DC = getDeclContext()->getRedeclContext();
+ if (!DC->isTranslationUnit())
+ return ReservedIdentifierStatus::NotReserved;
+ }
+
+ return Status;
+}
+
ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const {
StringRef name = getName();
if (name.empty()) return SFF_None;
diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp
index cedc94a935504..e59153060c678 100644
--- a/clang/lib/Basic/IdentifierTable.cpp
+++ b/clang/lib/Basic/IdentifierTable.cpp
@@ -273,6 +273,39 @@ bool IdentifierInfo::isCPlusPlusKeyword(const LangOptions &LangOpts) const {
return !isKeyword(LangOptsNoCPP);
}
+ReservedIdentifierStatus
+IdentifierInfo::isReserved(const LangOptions &LangOpts) const {
+ StringRef Name = getName();
+
+ // '_' is a reserved identifier, but its use is so common (e.g. to store
+ // ignored values) that we don't warn on it.
+ if (Name.size() <= 1)
+ return ReservedIdentifierStatus::NotReserved;
+
+ // [lex.name] p3
+ if (Name[0] == '_') {
+
+ // Each name that begins with an underscore followed by an uppercase letter
+ // or another underscore is reserved.
+ if (Name[1] == '_')
+ return ReservedIdentifierStatus::StartsWithDoubleUnderscore;
+
+ if ('A' <= Name[1] && Name[1] <= 'Z')
+ return ReservedIdentifierStatus::
+ StartsWithUnderscoreFollowedByCapitalLetter;
+
+ // This is a bit misleading: it actually means it's only reserved if we're
+ // at global scope because it starts with an underscore.
+ return ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope;
+ }
+
+ // Each name that contains a double underscore (__) is reserved.
+ if (LangOpts.CPlusPlus && Name.contains("__"))
+ return ReservedIdentifierStatus::ContainsDoubleUnderscore;
+
+ return ReservedIdentifierStatus::NotReserved;
+}
+
tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
// We use a perfect hash function here involving the length of the keyword,
// the first and third character. For preprocessor ID's there are no
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 290cdbf8c4e34..3d96bf1964e1e 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -4058,9 +4058,9 @@ void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
if (CalleeDecl->getBuiltinID() != 0 || CalleeDecl->hasAttr<NoDebugAttr>() ||
getCallSiteRelatedAttrs() == llvm::DINode::FlagZero)
return;
- if (const auto *Id = CalleeDecl->getIdentifier())
- if (Id->isReservedName())
- return;
+ if (CalleeDecl->isReserved(CGM.getLangOpts()) !=
+ ReservedIdentifierStatus::NotReserved)
+ return;
// If there is no DISubprogram attached to the function being called,
// create the one describing the function in order to have complete
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 4330024e60ccb..8893bd2cf00e7 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -739,18 +739,17 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
// Filter out names reserved for the implementation if they come from a
// system header.
static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
- const IdentifierInfo *Id = ND->getIdentifier();
- if (!Id)
- return false;
-
+ ReservedIdentifierStatus Status = ND->isReserved(SemaRef.getLangOpts());
// Ignore reserved names for compiler provided decls.
- if (Id->isReservedName() && ND->getLocation().isInvalid())
+ if ((Status != ReservedIdentifierStatus::NotReserved) &&
+ (Status != ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope) &&
+ ND->getLocation().isInvalid())
return true;
// For system headers ignore only double-underscore names.
// This allows for system headers providing private symbols with a single
// underscore.
- if (Id->isReservedName(/*doubleUnderscoreOnly=*/true) &&
+ if (Status == ReservedIdentifierStatus::StartsWithDoubleUnderscore &&
SemaRef.SourceMgr.isInSystemHeader(
SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
return true;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index f95bd7fe5634f..1abb692413b9d 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1516,6 +1516,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
} else {
IdResolver.AddDecl(D);
}
+ warnOnReservedIdentifier(D);
}
bool Sema::isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S,
@@ -5558,6 +5559,18 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
return false;
}
+void Sema::warnOnReservedIdentifier(const NamedDecl *D) {
+ // Avoid warning twice on the same identifier, and don't warn on redeclaration
+ // of system decl.
+ if (D->getPreviousDecl() || D->isImplicit())
+ return;
+ ReservedIdentifierStatus Status = D->isReserved(getLangOpts());
+ if (Status != ReservedIdentifierStatus::NotReserved &&
+ !Context.getSourceManager().isInSystemHeader(D->getLocation()))
+ Diag(D->getLocation(), diag::warn_reserved_extern_symbol)
+ << D << static_cast<int>(Status);
+}
+
Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg());
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 342b1be23638d..e1665997729d5 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -16778,6 +16778,8 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
}
}
+ warnOnReservedIdentifier(ND);
+
return ND;
}
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index a3b1fa4ab5348..70c96620323ff 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -542,6 +542,12 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
return SubStmt;
}
+ ReservedIdentifierStatus Status = TheDecl->isReserved(getLangOpts());
+ if (Status != ReservedIdentifierStatus::NotReserved &&
+ !Context.getSourceManager().isInSystemHeader(IdentLoc))
+ Diag(IdentLoc, diag::warn_reserved_extern_symbol)
+ << TheDecl << static_cast<int>(Status);
+
// Otherwise, things are good. Fill in the declaration and return it.
LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt);
TheDecl->setStmt(LS);
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 7a65c2a6fe2c2..a2082814a4e82 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1677,6 +1677,9 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
if (ExportLoc.isValid())
Diag(ExportLoc, diag::warn_template_export_unsupported);
+ for (NamedDecl *P : Params)
+ warnOnReservedIdentifier(P);
+
return TemplateParameterList::Create(
Context, TemplateLoc, LAngleLoc,
llvm::makeArrayRef(Params.data(), Params.size()),
diff --git a/clang/test/Preprocessor/macro-reserved.c b/clang/test/Preprocessor/macro-reserved.c
index 84b9262cb82ec..899074e799aff 100644
--- a/clang/test/Preprocessor/macro-reserved.c
+++ b/clang/test/Preprocessor/macro-reserved.c
@@ -46,7 +46,7 @@
#define volatile // expected-warning {{keyword is hidden by macro definition}}
#undef volatile
-#pragma clang diagnostic warning "-Wreserved-id-macro"
+#pragma clang diagnostic warning "-Wreserved-macro-identifier"
#define switch if // expected-warning {{keyword is hidden by macro definition}}
#define final 1
diff --git a/clang/test/Preprocessor/macro-reserved.cpp b/clang/test/Preprocessor/macro-reserved.cpp
index d1f70317f7aaa..f06d75cbf1af7 100644
--- a/clang/test/Preprocessor/macro-reserved.cpp
+++ b/clang/test/Preprocessor/macro-reserved.cpp
@@ -47,8 +47,7 @@
#define volatile // expected-warning {{keyword is hidden by macro definition}}
#undef volatile
-
-#pragma clang diagnostic warning "-Wreserved-id-macro"
+#pragma clang diagnostic warning "-Wreserved-macro-identifier"
#define switch if // expected-warning {{keyword is hidden by macro definition}}
#define final 1
diff --git a/clang/test/Sema/reserved-identifier.c b/clang/test/Sema/reserved-identifier.c
new file mode 100644
index 0000000000000..2ee7fc63751ff
--- /dev/null
+++ b/clang/test/Sema/reserved-identifier.c
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wreserved-identifier -Wno-visibility %s
+
+#define __oof foo__ // expected-warning {{macro name is a reserved identifier}}
+
+int foo__bar() { return 0; } // no-warning
+static int _bar() { return 0; } // expected-warning {{identifier '_bar' is reserved because it starts with '_' at global scope}}
+static int _Bar() { return 0; } // expected-warning {{identifier '_Bar' is reserved because it starts with '_' followed by a capital letter}}
+int _foo() { return 0; } // expected-warning {{identifier '_foo' is reserved because it starts with '_' at global scope}}
+
+// This one is explicitly skipped by -Wreserved-identifier
+void *_; // no-warning
+
+void foo(unsigned int _Reserved) { // expected-warning {{identifier '_Reserved' is reserved because it starts with '_' followed by a capital letter}}
+ unsigned int __1 = // expected-warning {{identifier '__1' is reserved because it starts with '__'}}
+ _Reserved; // no-warning
+ goto __reserved; // expected-warning {{identifier '__reserved' is reserved because it starts with '__'}}
+__reserved: // expected-warning {{identifier '__reserved' is reserved because it starts with '__'}}
+ ;
+}
+
+void foot(unsigned int _not_reserved) {} // no-warning
+
+enum __menu { // expected-warning {{identifier '__menu' is reserved because it starts with '__'}}
+ __some, // expected-warning {{identifier '__some' is reserved because it starts with '__'}}
+ _Other, // expected-warning {{identifier '_Other' is reserved because it starts with '_' followed by a capital letter}}
+ _other // expected-warning {{identifier '_other' is reserved because it starts with '_' at global scope}}
+};
+
+struct __babar { // expected-warning {{identifier '__babar' is reserved because it starts with '__'}}
+};
+
+struct _Zebulon; // expected-warning {{identifier '_Zebulon' is reserved because it starts with '_' followed by a capital letter}}
+struct _Zebulon2 { // expected-warning {{identifier '_Zebulon2' is reserved because it starts with '_' followed by a capital letter}}
+} * p;
+struct _Zebulon3 *pp; // expected-warning {{identifier '_Zebulon3' is reserved because it starts with '_' followed by a capital letter}}
+
+typedef struct {
+ int _Field; // expected-warning {{identifier '_Field' is reserved because it starts with '_' followed by a capital letter}}
+ int _field; // no-warning
+} _Typedef; // expected-warning {{identifier '_Typedef' is reserved because it starts with '_' followed by a capital letter}}
+
+int foobar() {
+ return foo__bar(); // no-warning
+}
+
+struct _reserved { // expected-warning {{identifier '_reserved' is reserved because it starts with '_' at global scope}}
+ int a;
+} cunf(void) {
+ return (struct _reserved){1};
+}
+
+// FIXME: According to clang declaration context layering, _preserved belongs to
+// the translation unit, so we emit a warning. It's unclear that's what the
+// standard mandate, but it's such a corner case we can live with it.
+void func(struct _preserved { int a; } r) {} // expected-warning {{identifier '_preserved' is reserved because it starts with '_' at global scope}}
+
+extern char *_strdup(const char *); // expected-warning {{identifier '_strdup' is reserved because it starts with '_' at global scope}}
+
+// Don't warn on redecleration
+extern char *_strdup(const char *); // no-warning
+
+void ok() {
+ void _ko(); // expected-warning {{identifier '_ko' is reserved because it starts with '_' at global scope}}
+ extern int _ko_again; // expected-warning {{identifier '_ko_again' is reserved because it starts with '_' at global scope}}
+}
diff --git a/clang/test/Sema/reserved-identifier.cpp b/clang/test/Sema/reserved-identifier.cpp
new file mode 100644
index 0000000000000..1992f6976c38f
--- /dev/null
+++ b/clang/test/Sema/reserved-identifier.cpp
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify -Wreserved-identifier %s
+
+int foo__bar() { return 0; } // expected-warning {{identifier 'foo__bar' is reserved because it contains '__'}}
+static int _bar() { return 0; } // expected-warning {{identifier '_bar' is reserved because it starts with '_' at global scope}}
+static int _Bar() { return 0; } // expected-warning {{identifier '_Bar' is reserved because it starts with '_' followed by a capital letter}}
+int _barbouille() { return 0; } // expected-warning {{identifier '_barbouille' is reserved because it starts with '_' at global scope}}
+
+void foo(unsigned int _Reserved) { // expected-warning {{identifier '_Reserved' is reserved because it starts with '_' followed by a capital letter}}
+ unsigned int __1 = // expected-warning {{identifier '__1' is reserved because it starts with '__'}}
+ _Reserved; // no-warning
+}
+
+// This one is explicitly skipped by -Wreserved-identifier
+void *_; // no-warning
+
+template <class T> constexpr bool __toucan = true; // expected-warning {{identifier '__toucan' is reserved because it starts with '__'}}
+
+template <class T>
+concept _Barbotine = __toucan<T>; // expected-warning {{identifier '_Barbotine' is reserved because it starts with '_' followed by a capital letter}}
+
+template <class __> // expected-warning {{'__' is reserved because it starts with '__'}}
+struct BarbeNoire {};
+
+template <class _not_reserved> // no-warning
+struct BarbeJaune {};
+
+template <class __> // expected-warning {{'__' is reserved because it starts with '__'}}
+void BarbeRousse() {}
+
+namespace _Barbidur { // expected-warning {{identifier '_Barbidur' is reserved because it starts with '_' followed by a capital letter}}
+
+struct __barbidou {}; // expected-warning {{identifier '__barbidou' is reserved because it starts with '__'}}
+struct _barbidou {}; // no-warning
+
+int __barbouille; // expected-warning {{identifier '__barbouille' is reserved because it starts with '__'}}
+int _barbouille; // no-warning
+
+int __babar() { return 0; } // expected-warning {{identifier '__babar' is reserved because it starts with '__'}}
+int _babar() { return 0; } // no-warning
+
+} // namespace _Barbidur
+
+class __barbapapa { // expected-warning {{identifier '__barbapapa' is reserved because it starts with '__'}}
+ void _barbabelle() {} // no-warning
+ int _Barbalala; // expected-warning {{identifier '_Barbalala' is reserved because it starts with '_' followed by a capital letter}}
+};
+
+enum class __menu { // expected-warning {{identifier '__menu' is reserved because it starts with '__'}}
+ __some, // expected-warning {{identifier '__some' is reserved because it starts with '__'}}
+ _Other, // expected-warning {{identifier '_Other' is reserved because it starts with '_' followed by a capital letter}}
+ _other // no-warning
+};
+
+enum _Menu { // expected-warning {{identifier '_Menu' is reserved because it starts with '_' followed by a capital letter}}
+ _OtheR_, // expected-warning {{identifier '_OtheR_' is reserved because it starts with '_' followed by a capital letter}}
+ _other_ // expected-warning {{identifier '_other_' is reserved because it starts with '_' at global scope}}
+};
+
+enum {
+ __some, // expected-warning {{identifier '__some' is reserved because it starts with '__'}}
+ _Other, // expected-warning {{identifier '_Other' is reserved because it starts with '_' followed by a capital letter}}
+ _other // expected-warning {{identifier '_other' is reserved because it starts with '_' at global scope}}
+};
+
+static union {
+ int _barbeFleurie; // no-warning
+};
+
+using _Barbamama = __barbapapa; // expected-warning {{identifier '_Barbamama' is reserved because it starts with '_' followed by a capital letter}}
+
+int foobar() {
+ return foo__bar(); // no-warning
+}
+
+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}}
+{
+ return 0.;
+}
+
+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}}
+} * q;
+
+struct Any {
+ friend void _barbegrise(); // expected-warning {{identifier '_barbegrise' is reserved because it starts with '_' at global scope}}
+};
More information about the cfe-commits
mailing list