diff options
-rw-r--r-- | clang/include/clang/Basic/Attr.td | 20 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 47 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 18 | ||||
-rw-r--r-- | clang/utils/TableGen/ClangAttrEmitter.cpp | 83 |
4 files changed, 69 insertions, 99 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 667250eb519..5d81bbf4f5e 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -131,8 +131,6 @@ class Attr { bit SemaHandler = 1; // Set to true for attributes that are completely ignored. bit Ignored = 0; - // Set to true if each of the spellings is a distinct attribute. - bit DistinctSpellings = 0; // Set to true if the attribute's parsing does not match its semantic // content. Eg) It parses 3 args, but semantically takes 4 args. Opts out of // common attribute error checking. @@ -662,12 +660,18 @@ def Override : InheritableAttr { def Ownership : InheritableAttr { let Spellings = [GNU<"ownership_holds">, GNU<"ownership_returns">, GNU<"ownership_takes">]; - let DistinctSpellings = 1; - let Args = [EnumArgument<"OwnKind", "OwnershipKind", - ["ownership_holds", "ownership_returns", "ownership_takes"], - ["Holds", "Returns", "Takes"]>, - StringArgument<"Module">, VariadicUnsignedArgument<"Args">]; - let HasCustomParsing = 1; + let Accessors = [Accessor<"isHolds", [GNU<"ownership_holds">]>, + Accessor<"isReturns", [GNU<"ownership_returns">]>, + Accessor<"isTakes", [GNU<"ownership_takes">]>]; + let AdditionalMembers = [{ + enum OwnershipKind { Holds, Returns, Takes }; + OwnershipKind getOwnKind() const { + return isHolds() ? Holds : + isTakes() ? Takes : + Returns; + } + }]; + let Args = [IdentifierArgument<"Module">, VariadicUnsignedArgument<"Args">]; } def Packed : InheritableAttr { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 24009768f46..eff42954bf3 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1546,34 +1546,26 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { return; } - // Figure out our Kind, and check arguments while we're at it. - OwnershipAttr::OwnershipKind K; - switch (AL.getKind()) { - case AttributeList::AT_ownership_takes: - K = OwnershipAttr::Takes; - if (AL.getNumArgs() < 2) { - S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2; - return; - } - break; - case AttributeList::AT_ownership_holds: - K = OwnershipAttr::Holds; + // Figure out our Kind. + OwnershipAttr::OwnershipKind K = + OwnershipAttr(AL.getLoc(), S.Context, 0, 0, 0, + AL.getAttributeSpellingListIndex()).getOwnKind(); + + // Check arguments. + switch (K) { + case OwnershipAttr::Takes: + case OwnershipAttr::Holds: if (AL.getNumArgs() < 2) { S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2; return; } break; - case AttributeList::AT_ownership_returns: - K = OwnershipAttr::Returns; - + case OwnershipAttr::Returns: if (AL.getNumArgs() > 2) { S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << 1; return; } break; - default: - // This should never happen given how we are called. - llvm_unreachable("Unknown ownership attribute"); } if (!isFunction(D) || !hasFunctionProto(D)) { @@ -1582,11 +1574,15 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { return; } - StringRef Module = AL.getArgAsIdent(0)->Ident->getName(); + IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident; // Normalize the argument, __foo__ becomes foo. - if (Module.startswith("__") && Module.endswith("__")) - Module = Module.substr(2, Module.size() - 4); + StringRef ModuleName = Module->getName(); + if (ModuleName.startswith("__") && ModuleName.endswith("__") && + ModuleName.size() > 4) { + ModuleName = ModuleName.drop_front(2).drop_back(2); + Module = &S.PP.getIdentifierTable().get(ModuleName); + } SmallVector<unsigned, 8> OwnershipArgs; for (unsigned i = 1; i < AL.getNumArgs(); ++i) { @@ -1620,6 +1616,8 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { for (specific_attr_iterator<OwnershipAttr> i = D->specific_attr_begin<OwnershipAttr>(), e = D->specific_attr_end<OwnershipAttr>(); i != e; ++i) { + // FIXME: A returns attribute should conflict with any returns attribute + // with a different index too. if ((*i)->getOwnKind() != K && (*i)->args_end() != std::find((*i)->args_begin(), (*i)->args_end(), Idx)) { S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) @@ -1635,7 +1633,7 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { llvm::array_pod_sort(start, start + size); D->addAttr(::new (S.Context) - OwnershipAttr(AL.getLoc(), S.Context, K, Module, start, size, + OwnershipAttr(AL.getLoc(), S.Context, Module, start, size, AL.getAttributeSpellingListIndex())); } @@ -4698,10 +4696,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_NoCommon: handleNoCommonAttr (S, D, Attr); break; case AttributeList::AT_NonNull: handleNonNullAttr (S, D, Attr); break; case AttributeList::AT_Overloadable:handleOverloadableAttr(S, D, Attr); break; - case AttributeList::AT_ownership_returns: - case AttributeList::AT_ownership_takes: - case AttributeList::AT_ownership_holds: - handleOwnershipAttr (S, D, Attr); break; + case AttributeList::AT_Ownership: handleOwnershipAttr (S, D, Attr); break; case AttributeList::AT_Cold: handleColdAttr (S, D, Attr); break; case AttributeList::AT_Hot: handleHotAttr (S, D, Attr); break; case AttributeList::AT_Naked: handleNakedAttr (S, D, Attr); break; diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index c7aa0fb150c..e5e016ca6d0 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -234,9 +234,9 @@ private: bool isAllocationFunction(const FunctionDecl *FD, ASTContext &C) const; bool isStandardNewDelete(const FunctionDecl *FD, ASTContext &C) const; ///@} - static ProgramStateRef MallocMemReturnsAttr(CheckerContext &C, - const CallExpr *CE, - const OwnershipAttr* Att); + ProgramStateRef MallocMemReturnsAttr(CheckerContext &C, + const CallExpr *CE, + const OwnershipAttr* Att) const; static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE, const Expr *SizeEx, SVal Init, ProgramStateRef State, @@ -729,10 +729,10 @@ void MallocChecker::checkPostObjCMessage(const ObjCMethodCall &Call, C.addTransition(State); } -ProgramStateRef MallocChecker::MallocMemReturnsAttr(CheckerContext &C, - const CallExpr *CE, - const OwnershipAttr* Att) { - if (Att->getModule() != "malloc") +ProgramStateRef +MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, + const OwnershipAttr *Att) const { + if (Att->getModule() != II_malloc) return 0; OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end(); @@ -804,8 +804,8 @@ ProgramStateRef MallocChecker::MallocUpdateRefState(CheckerContext &C, ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE, - const OwnershipAttr* Att) const { - if (Att->getModule() != "malloc") + const OwnershipAttr *Att) const { + if (Att->getModule() != II_malloc) return 0; ProgramStateRef State = C.getState(); diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 71eaf131dd3..d8fdbe0dc0f 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -1513,39 +1513,29 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) { continue; std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings"); - // Each distinct spelling yields an attribute kind. - if (R.getValueAsBit("DistinctSpellings")) { - for (unsigned I = 0; I < Spellings.size(); ++ I) { - OS << - " case AT_" << Spellings[I]->getValueAsString("Name") << ": \n" - " Index = " << I << ";\n" - " break;\n"; - } - } else { - OS << " case AT_" << R.getName() << " : {\n"; - for (unsigned I = 0; I < Spellings.size(); ++ I) { - SmallString<16> Namespace; - if (Spellings[I]->getValueAsString("Variety") == "CXX11") - Namespace = Spellings[I]->getValueAsString("Namespace"); - else - Namespace = ""; - - OS << " if (Name == \"" - << Spellings[I]->getValueAsString("Name") << "\" && " - << "SyntaxUsed == " - << StringSwitch<unsigned>(Spellings[I]->getValueAsString("Variety")) - .Case("GNU", 0) - .Case("CXX11", 1) - .Case("Declspec", 2) - .Case("Keyword", 3) - .Default(0) - << " && Scope == \"" << Namespace << "\")\n" - << " return " << I << ";\n"; - } + OS << " case AT_" << R.getName() << " : {\n"; + for (unsigned I = 0; I < Spellings.size(); ++ I) { + SmallString<16> Namespace; + if (Spellings[I]->getValueAsString("Variety") == "CXX11") + Namespace = Spellings[I]->getValueAsString("Namespace"); + else + Namespace = ""; - OS << " break;\n"; - OS << " }\n"; + OS << " if (Name == \"" + << Spellings[I]->getValueAsString("Name") << "\" && " + << "SyntaxUsed == " + << StringSwitch<unsigned>(Spellings[I]->getValueAsString("Variety")) + .Case("GNU", 0) + .Case("CXX11", 1) + .Case("Declspec", 2) + .Case("Keyword", 3) + .Default(0) + << " && Scope == \"" << Namespace << "\")\n" + << " return " << I << ";\n"; } + + OS << " break;\n"; + OS << " }\n"; } OS << " }\n"; @@ -1662,26 +1652,10 @@ static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records) { for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { Record &Attr = **I; - - bool SemaHandler = Attr.getValueAsBit("SemaHandler"); - bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); - - if (SemaHandler) { - if (DistinctSpellings) { - std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); - - for (std::vector<Record*>::const_iterator I = Spellings.begin(), - E = Spellings.end(); I != E; ++I) { - std::string AttrName = (*I)->getValueAsString("Name"); - - StringRef Spelling = NormalizeAttrName(AttrName); - R.push_back(std::make_pair(Spelling.str(), &Attr)); - } - } else { - StringRef AttrName = Attr.getName(); - AttrName = NormalizeAttrName(AttrName); - R.push_back(std::make_pair(AttrName.str(), *I)); - } + if (Attr.getValueAsBit("SemaHandler")) { + StringRef AttrName = Attr.getName(); + AttrName = NormalizeAttrName(AttrName); + R.push_back(std::make_pair(AttrName.str(), *I)); } } return R; @@ -1750,19 +1724,16 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { Record &Attr = **I; - + bool SemaHandler = Attr.getValueAsBit("SemaHandler"); bool Ignored = Attr.getValueAsBit("Ignored"); - bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); if (SemaHandler || Ignored) { std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); + StringRef AttrName = NormalizeAttrName(StringRef(Attr.getName())); for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { std::string RawSpelling = (*I)->getValueAsString("Name"); - StringRef AttrName = NormalizeAttrName(DistinctSpellings - ? StringRef(RawSpelling) - : StringRef(Attr.getName())); SmallString<64> Spelling; if ((*I)->getValueAsString("Variety") == "CXX11") { |