diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 105 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 13 |
2 files changed, 83 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) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9403dd9fbaa..625760c68ca 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -227,6 +227,14 @@ static void instantiateDependentCUDALaunchBoundsAttr( Attr.getSpellingListIndex()); } +static void +instantiateDependentModeAttr(Sema &S, + const MultiLevelTemplateArgumentList &TemplateArgs, + const ModeAttr &Attr, Decl *New) { + S.AddModeAttr(Attr.getRange(), New, Attr.getMode(), + Attr.getSpellingListIndex(), /*InInstantiation=*/true); +} + void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -265,6 +273,11 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, continue; } + if (const ModeAttr *Mode = dyn_cast<ModeAttr>(TmplAttr)) { + instantiateDependentModeAttr(*this, TemplateArgs, *Mode, New); + continue; + } + // Existing DLL attribute on the instantiation takes precedence. if (TmplAttr->getKind() == attr::DLLExport || TmplAttr->getKind() == attr::DLLImport) { |