summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDeclAttr.cpp
diff options
context:
space:
mode:
authorDenis Zobnin <d.zobnin.bugzilla@gmail.com>2016-02-02 13:50:39 +0000
committerDenis Zobnin <d.zobnin.bugzilla@gmail.com>2016-02-02 13:50:39 +0000
commitd9e2dcdb424f761f7148db63d7ed9cd6ae40c2fe (patch)
tree44f2883b09f30910f93e93b55b4271d31f73f0f9 /clang/lib/Sema/SemaDeclAttr.cpp
parent96fe4ef5f7867bde5c95a59a96fa802ff9eb6cf4 (diff)
downloadbcm5719-llvm-d9e2dcdb424f761f7148db63d7ed9cd6ae40c2fe.tar.gz
bcm5719-llvm-d9e2dcdb424f761f7148db63d7ed9cd6ae40c2fe.zip
Fix for PR8901: attribute "mode" rejected for enums and dependent types.
Allow "mode" attribute for enum types, except for vector modes, for compatibility with GCC. Support "mode" attribute with dependent types. Differential Revision: http://reviews.llvm.org/D16219 llvm-svn: 259497
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp105
1 files changed, 70 insertions, 35 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index eb8a49c9745..81a57b222fd 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3297,6 +3297,8 @@ bool Sema::checkMSInheritanceAttrOnDefinition(
/// attribute.
static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
bool &IntegerMode, bool &ComplexMode) {
+ IntegerMode = true;
+ ComplexMode = false;
switch (Str.size()) {
case 2:
switch (Str[0]) {
@@ -3363,9 +3365,15 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident;
- StringRef Str = Name->getName();
+ S.AddModeAttr(Attr.getRange(), D, Name, Attr.getAttributeSpellingListIndex());
+}
+
+void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
+ unsigned SpellingListIndex, bool InInstantiation) {
+ StringRef Str = Name->getName();
normalizeName(Str);
+ SourceLocation AttrLoc = AttrRange.getBegin();
unsigned DestWidth = 0;
bool IntegerMode = true;
@@ -3381,99 +3389,126 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (VectorStringLength &&
!Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
VectorSize.isPowerOf2()) {
- parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth,
+ parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth,
IntegerMode, ComplexMode);
- S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated);
+ // Avoid duplicate warning from template instantiation.
+ if (!InInstantiation)
+ Diag(AttrLoc, diag::warn_vector_mode_deprecated);
} else {
VectorSize = 0;
}
}
if (!VectorSize)
- parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode);
+ parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode);
+
+ // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
+ // and friends, at least with glibc.
+ // FIXME: Make sure floating-point mappings are accurate
+ // FIXME: Support XF and TF types
+ if (!DestWidth) {
+ Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name;
+ return;
+ }
QualType OldTy;
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
OldTy = TD->getUnderlyingType();
- else
+ else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
+ // Something like 'typedef enum { X } __attribute__((mode(XX))) T;'.
+ // Try to get type from enum declaration, default to int.
+ OldTy = ED->getIntegerType();
+ if (OldTy.isNull())
+ OldTy = Context.IntTy;
+ } else
OldTy = cast<ValueDecl>(D)->getType();
+ if (OldTy->isDependentType()) {
+ D->addAttr(::new (Context)
+ ModeAttr(AttrRange, Context, Name, SpellingListIndex));
+ return;
+ }
+
// Base type can also be a vector type (see PR17453).
// Distinguish between base type and base element type.
QualType OldElemTy = OldTy;
if (const VectorType *VT = OldTy->getAs<VectorType>())
OldElemTy = VT->getElementType();
- if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType())
- S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
+ // GCC allows 'mode' attribute on enumeration types (even incomplete), except
+ // for vector modes. So, 'enum X __attribute__((mode(QI)));' forms a complete
+ // type, 'enum { A } __attribute__((mode(V4SI)))' is rejected.
+ if ((isa<EnumDecl>(D) || OldElemTy->getAs<EnumType>()) &&
+ VectorSize.getBoolValue()) {
+ Diag(AttrLoc, diag::err_enum_mode_vector_type) << Name << AttrRange;
+ return;
+ }
+ bool IntegralOrAnyEnumType =
+ OldElemTy->isIntegralOrEnumerationType() || OldElemTy->getAs<EnumType>();
+
+ if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType() &&
+ !IntegralOrAnyEnumType)
+ Diag(AttrLoc, diag::err_mode_not_primitive);
else if (IntegerMode) {
- if (!OldElemTy->isIntegralOrEnumerationType())
- S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+ if (!IntegralOrAnyEnumType)
+ Diag(AttrLoc, diag::err_mode_wrong_type);
} else if (ComplexMode) {
if (!OldElemTy->isComplexType())
- S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+ Diag(AttrLoc, diag::err_mode_wrong_type);
} else {
if (!OldElemTy->isFloatingType())
- S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
- }
-
- // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
- // and friends, at least with glibc.
- // FIXME: Make sure floating-point mappings are accurate
- // FIXME: Support XF and TF types
- if (!DestWidth) {
- S.Diag(Attr.getLoc(), diag::err_machine_mode) << 0 /*Unknown*/ << Name;
- return;
+ Diag(AttrLoc, diag::err_mode_wrong_type);
}
QualType NewElemTy;
if (IntegerMode)
- NewElemTy = S.Context.getIntTypeForBitwidth(
- DestWidth, OldElemTy->isSignedIntegerType());
+ NewElemTy = Context.getIntTypeForBitwidth(DestWidth,
+ OldElemTy->isSignedIntegerType());
else
- NewElemTy = S.Context.getRealTypeForBitwidth(DestWidth);
+ NewElemTy = Context.getRealTypeForBitwidth(DestWidth);
if (NewElemTy.isNull()) {
- S.Diag(Attr.getLoc(), diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
+ Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
return;
}
if (ComplexMode) {
- NewElemTy = S.Context.getComplexType(NewElemTy);
+ NewElemTy = Context.getComplexType(NewElemTy);
}
QualType NewTy = NewElemTy;
if (VectorSize.getBoolValue()) {
- NewTy = S.Context.getVectorType(NewTy, VectorSize.getZExtValue(),
- VectorType::GenericVector);
+ NewTy = Context.getVectorType(NewTy, VectorSize.getZExtValue(),
+ VectorType::GenericVector);
} else if (const VectorType *OldVT = OldTy->getAs<VectorType>()) {
// Complex machine mode does not support base vector types.
if (ComplexMode) {
- S.Diag(Attr.getLoc(), diag::err_complex_mode_vector_type);
+ Diag(AttrLoc, diag::err_complex_mode_vector_type);
return;
}
- unsigned NumElements = S.Context.getTypeSize(OldElemTy) *
+ unsigned NumElements = Context.getTypeSize(OldElemTy) *
OldVT->getNumElements() /
- S.Context.getTypeSize(NewElemTy);
+ Context.getTypeSize(NewElemTy);
NewTy =
- S.Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind());
+ Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind());
}
if (NewTy.isNull()) {
- S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+ Diag(AttrLoc, diag::err_mode_wrong_type);
return;
}
// Install the new type.
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy);
+ else if (EnumDecl *ED = dyn_cast<EnumDecl>(D))
+ ED->setIntegerType(NewTy);
else
cast<ValueDecl>(D)->setType(NewTy);
- D->addAttr(::new (S.Context)
- ModeAttr(Attr.getRange(), S.Context, Name,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (Context)
+ ModeAttr(AttrRange, Context, Name, SpellingListIndex));
}
static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
OpenPOWER on IntegriCloud