mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-05 21:12:31 +00:00
Handle unscoped enumeration in nested name specifier.
If an unscoped enum is used as a nested name specifier and the language dialect is not C++ 11, issue an extension warning. This fixes PR16951. Differential Revision: http://reviews.llvm.org/D6389 llvm-svn: 226413
This commit is contained in:
parent
4843f193ad
commit
25a8afa957
@ -1231,6 +1231,9 @@ def warn_cxx98_compat_enum_nested_name_spec : Warning<
|
||||
def err_nested_name_spec_is_not_class : Error<
|
||||
"%0 cannot appear before '::' because it is not a class"
|
||||
"%select{ or namespace|, namespace, or enumeration}1; did you mean ':'?">;
|
||||
def ext_nested_name_spec_is_enum : ExtWarn<
|
||||
"use of enumeration in a nested name specifier is a C++11 extension">,
|
||||
InGroup<CXX11>;
|
||||
|
||||
// C++ class members
|
||||
def err_storageclass_invalid_for_member : Error<
|
||||
|
@ -4632,7 +4632,8 @@ public:
|
||||
bool ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
|
||||
SourceLocation ColonColonLoc, CXXScopeSpec &SS);
|
||||
|
||||
bool isAcceptableNestedNameSpecifier(const NamedDecl *SD);
|
||||
bool isAcceptableNestedNameSpecifier(const NamedDecl *SD,
|
||||
bool *CanCorrect = nullptr);
|
||||
NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
|
||||
|
||||
bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
|
||||
|
@ -282,7 +282,11 @@ bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
|
||||
|
||||
/// \brief Determines whether the given declaration is an valid acceptable
|
||||
/// result for name lookup of a nested-name-specifier.
|
||||
bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD) {
|
||||
/// \param SD Declaration checked for nested-name-specifier.
|
||||
/// \param IsExtension If not null and the declaration is accepted as an
|
||||
/// extension, the pointed variable is assigned true.
|
||||
bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD,
|
||||
bool *IsExtension) {
|
||||
if (!SD)
|
||||
return false;
|
||||
|
||||
@ -298,14 +302,23 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD) {
|
||||
QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
|
||||
if (T->isDependentType())
|
||||
return true;
|
||||
else if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
|
||||
if (TD->getUnderlyingType()->isRecordType() ||
|
||||
(Context.getLangOpts().CPlusPlus11 &&
|
||||
TD->getUnderlyingType()->isEnumeralType()))
|
||||
if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
|
||||
if (TD->getUnderlyingType()->isRecordType())
|
||||
return true;
|
||||
} else if (isa<RecordDecl>(SD) ||
|
||||
(Context.getLangOpts().CPlusPlus11 && isa<EnumDecl>(SD)))
|
||||
if (TD->getUnderlyingType()->isEnumeralType()) {
|
||||
if (Context.getLangOpts().CPlusPlus11)
|
||||
return true;
|
||||
if (IsExtension)
|
||||
*IsExtension = true;
|
||||
}
|
||||
} else if (isa<RecordDecl>(SD)) {
|
||||
return true;
|
||||
} else if (isa<EnumDecl>(SD)) {
|
||||
if (Context.getLangOpts().CPlusPlus11)
|
||||
return true;
|
||||
if (IsExtension)
|
||||
*IsExtension = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -599,7 +612,13 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
|
||||
}
|
||||
|
||||
NamedDecl *SD = Found.getAsSingle<NamedDecl>();
|
||||
if (isAcceptableNestedNameSpecifier(SD)) {
|
||||
bool IsExtension = false;
|
||||
bool AcceptSpec = isAcceptableNestedNameSpecifier(SD, &IsExtension);
|
||||
if (!AcceptSpec && IsExtension) {
|
||||
AcceptSpec = true;
|
||||
Diag(IdentifierLoc, diag::ext_nested_name_spec_is_enum);
|
||||
}
|
||||
if (AcceptSpec) {
|
||||
if (!ObjectType.isNull() && !ObjectTypeSearchedInScope &&
|
||||
!getLangOpts().CPlusPlus11) {
|
||||
// C++03 [basic.lookup.classref]p4:
|
||||
|
@ -13,7 +13,8 @@ int A::*pdi1;
|
||||
int (::A::*pdi2);
|
||||
int (A::*pfi)(int);
|
||||
|
||||
int B::*pbi; // expected-error {{'B' is not a class, namespace, or enumeration}}
|
||||
int B::*pbi; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
|
||||
// expected-error {{'pbi' does not point into a class}}
|
||||
int C::*pci; // expected-error {{'pci' does not point into a class}}
|
||||
void A::*pdv; // expected-error {{'pdv' declared as a member pointer to void}}
|
||||
int& A::*pdr; // expected-error {{'pdr' declared as a member pointer to a reference}}
|
||||
|
@ -115,8 +115,8 @@ namespace E {
|
||||
X = 0
|
||||
};
|
||||
|
||||
void f() {
|
||||
return E::X; // expected-error{{'E::Nested::E' is not a class, namespace, or enumeration}}
|
||||
int f() {
|
||||
return E::X; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -410,3 +410,28 @@ struct S7c {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace PR16951 {
|
||||
namespace ns {
|
||||
enum an_enumeration {
|
||||
ENUMERATOR // expected-note{{'ENUMERATOR' declared here}}
|
||||
};
|
||||
}
|
||||
|
||||
int x1 = ns::an_enumeration::ENUMERATOR; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
|
||||
|
||||
int x2 = ns::an_enumeration::ENUMERATOR::vvv; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
|
||||
// expected-error{{'ENUMERATOR' is not a class, namespace, or enumeration}} \
|
||||
|
||||
int x3 = ns::an_enumeration::X; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
|
||||
// expected-error{{no member named 'X'}}
|
||||
|
||||
enum enumerator_2 {
|
||||
ENUMERATOR_2
|
||||
};
|
||||
|
||||
int x4 = enumerator_2::ENUMERATOR_2; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
|
||||
int x5 = enumerator_2::X2; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
|
||||
// expected-error{{no member named 'X2' in 'PR16951::enumerator_2'}}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user