diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/TypePrinter.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 32 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 28 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 2 |
9 files changed, 64 insertions, 25 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 49ac8c1423f..619af9af0af 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -8241,6 +8241,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, return QualType(); if (lbaseInfo.getNoCallerSavedRegs() != rbaseInfo.getNoCallerSavedRegs()) return QualType(); + if (lbaseInfo.getNoCfCheck() != rbaseInfo.getNoCfCheck()) + return QualType(); // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'. bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn(); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index da7fdb0ee14..99f5b1384ad 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3129,6 +3129,7 @@ bool AttributedType::isQualifier() const { case AttributedType::attr_uptr: case AttributedType::attr_objc_kindof: case AttributedType::attr_ns_returns_retained: + case AttributedType::attr_nocf_check: return false; } llvm_unreachable("bad attributed type kind"); @@ -3166,6 +3167,7 @@ bool AttributedType::isCallingConv() const { case attr_nullable: case attr_null_unspecified: case attr_objc_kindof: + case attr_nocf_check: return false; case attr_pcs: diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index c28ada7dcb8..d46f8d3348e 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -801,6 +801,8 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info, << Info.getRegParm() << ")))"; if (Info.getNoCallerSavedRegs()) OS << " __attribute__((no_caller_saved_registers))"; + if (Info.getNoCfCheck()) + OS << " __attribute__((nocf_check))"; } void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T, @@ -1396,7 +1398,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, // FIXME: When Sema learns to form this AttributedType, avoid printing the // attribute again in printFunctionProtoAfter. case AttributedType::attr_noreturn: OS << "noreturn"; break; - + case AttributedType::attr_nocf_check: OS << "nocf_check"; break; case AttributedType::attr_cdecl: OS << "cdecl"; break; case AttributedType::attr_fastcall: OS << "fastcall"; break; case AttributedType::attr_stdcall: OS << "stdcall"; break; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 3a5505f6f63..41ed22e9866 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -803,6 +803,7 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, FI->NoReturn = info.getNoReturn(); FI->ReturnsRetained = info.getProducesResult(); FI->NoCallerSavedRegs = info.getNoCallerSavedRegs(); + FI->NoCfCheck = info.getNoCfCheck(); FI->Required = required; FI->HasRegParm = info.getHasRegParm(); FI->RegParm = info.getRegParm(); @@ -1850,6 +1851,8 @@ void CodeGenModule::ConstructAttributeList( RetAttrs.addAttribute(llvm::Attribute::NonNull); if (TargetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>()) FuncAttrs.addAttribute("no_caller_saved_registers"); + if (TargetDecl->hasAttr<AnyX86NoCfCheckAttr>()) + FuncAttrs.addAttribute(llvm::Attribute::NoCfCheck); HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>(); if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index ff8db474e18..330212a6d97 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2042,6 +2042,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, } } + if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) { + StringRef Name = A->getValue(); + if (Name == "full" || Name == "branch") { + Opts.CFProtectionBranch = 1; + } + } // -cl-std only applies for OpenCL language standards. // Override the -std option in this case. if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 6df1324fb38..260dfa5b180 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1908,9 +1908,6 @@ static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &AL) { static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &Attrs) { if (hasDeclarator(D)) return; - if (S.CheckNoReturnAttr(Attrs)) - return; - if (!isa<ObjCMethodDecl>(D)) { S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type) << Attrs.getName() << ExpectedFunctionOrMethod; @@ -1921,16 +1918,14 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &Attrs) { Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex())); } -static void handleNoCallerSavedRegsAttr(Sema &S, Decl *D, - const AttributeList &AL) { - if (S.CheckNoCallerSavedRegsAttr(AL)) - return; - - D->addAttr(::new (S.Context) AnyX86NoCallerSavedRegistersAttr( - AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); +static void handleNoCfCheckAttr(Sema &S, Decl *D, const AttributeList &Attrs) { + if (!S.getLangOpts().CFProtectionBranch) + S.Diag(Attrs.getLoc(), diag::warn_nocf_check_attribute_ignored); + else + handleSimpleAttribute<AnyX86NoCfCheckAttr>(S, D, Attrs); } -bool Sema::CheckNoReturnAttr(const AttributeList &Attrs) { +bool Sema::CheckAttrNoArgs(const AttributeList &Attrs) { if (!checkAttributeNumArgs(*this, Attrs, 0)) { Attrs.setInvalid(); return true; @@ -1939,7 +1934,7 @@ bool Sema::CheckNoReturnAttr(const AttributeList &Attrs) { return false; } -bool Sema::CheckNoCallerSavedRegsAttr(const AttributeList &AL) { +bool Sema::CheckAttrTarget(const AttributeList &AL) { // Check whether the attribute is valid on the current target. if (!AL.existsInTarget(Context.getTargetInfo())) { Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName(); @@ -1947,11 +1942,6 @@ bool Sema::CheckNoCallerSavedRegsAttr(const AttributeList &AL) { return true; } - if (!checkAttributeNumArgs(*this, AL, 0)) { - AL.setInvalid(); - return true; - } - return false; } @@ -5756,6 +5746,9 @@ static bool handleCommonAttributeFeatures(Sema &S, Decl *D, return true; } + if (S.CheckAttrTarget(AL)) + return true; + return false; } @@ -6052,6 +6045,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_NoReturn: handleNoReturnAttr(S, D, AL); break; + case AttributeList::AT_AnyX86NoCfCheck: + handleNoCfCheckAttr(S, D, AL); + break; case AttributeList::AT_NoThrow: handleSimpleAttribute<NoThrowAttr>(S, D, AL); break; @@ -6427,7 +6423,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleTypeTagForDatatypeAttr(S, D, AL); break; case AttributeList::AT_AnyX86NoCallerSavedRegisters: - handleNoCallerSavedRegsAttr(S, D, AL); + handleSimpleAttribute<AnyX86NoCallerSavedRegistersAttr>(S, D, AL); break; case AttributeList::AT_RenderScriptKernel: handleSimpleAttribute<RenderScriptKernelAttr>(S, D, AL); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 9791003f656..acf22cda0f0 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -125,6 +125,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, case AttributeList::AT_NoReturn: \ case AttributeList::AT_Regparm: \ case AttributeList::AT_AnyX86NoCallerSavedRegisters: \ + case AttributeList::AT_AnyX86NoCfCheck: \ CALLING_CONV_ATTRS_CASELIST // Microsoft-specific type qualifiers. @@ -5144,6 +5145,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { return AttributeList::AT_ObjCOwnership; case AttributedType::attr_noreturn: return AttributeList::AT_NoReturn; + case AttributedType::attr_nocf_check: + return AttributeList::AT_AnyX86NoCfCheck; case AttributedType::attr_cdecl: return AttributeList::AT_CDecl; case AttributedType::attr_fastcall: @@ -6609,7 +6612,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, FunctionTypeUnwrapper unwrapped(S, type); if (attr.getKind() == AttributeList::AT_NoReturn) { - if (S.CheckNoReturnAttr(attr)) + if (S.CheckAttrNoArgs(attr)) return true; // Delay if this is not a function type. @@ -6649,7 +6652,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, } if (attr.getKind() == AttributeList::AT_AnyX86NoCallerSavedRegisters) { - if (S.CheckNoCallerSavedRegsAttr(attr)) + if (S.CheckAttrTarget(attr) || S.CheckAttrNoArgs(attr)) return true; // Delay if this is not a function type. @@ -6662,6 +6665,27 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, return true; } + if (attr.getKind() == AttributeList::AT_AnyX86NoCfCheck) { + if (!S.getLangOpts().CFProtectionBranch) { + S.Diag(attr.getLoc(), diag::warn_nocf_check_attribute_ignored); + attr.setInvalid(); + return true; + } + + if (S.CheckAttrTarget(attr) || S.CheckAttrNoArgs(attr)) + return true; + + // If this is not a function type, warning will be asserted by subject + // check. + if (!unwrapped.isFunctionType()) + return true; + + FunctionType::ExtInfo EI = + unwrapped.get()->getExtInfo().withNoCfCheck(true); + type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); + return true; + } + if (attr.getKind() == AttributeList::AT_Regparm) { unsigned value; if (S.CheckRegparmAttr(attr, value)) diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index b6fc4b22619..4cc3f9cb86a 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6005,13 +6005,14 @@ QualType ASTReader::readTypeRecord(unsigned Index) { } case TYPE_FUNCTION_NO_PROTO: { - if (Record.size() != 7) { + if (Record.size() != 8) { Error("incorrect encoding of no-proto function type"); return QualType(); } QualType ResultType = readType(*Loc.F, Record, Idx); FunctionType::ExtInfo Info(Record[1], Record[2], Record[3], - (CallingConv)Record[4], Record[5], Record[6]); + (CallingConv)Record[4], Record[5], Record[6], + Record[7]); return Context.getFunctionNoProtoType(ResultType, Info); } @@ -6024,9 +6025,10 @@ QualType ASTReader::readTypeRecord(unsigned Index) { /*regparm*/ Record[3], static_cast<CallingConv>(Record[4]), /*produces*/ Record[5], - /*nocallersavedregs*/ Record[6]); + /*nocallersavedregs*/ Record[6], + /*nocfcheck*/ Record[7]); - unsigned Idx = 7; + unsigned Idx = 8; EPI.Variadic = Record[Idx++]; EPI.HasTrailingReturn = Record[Idx++]; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 53e09b3f3fd..e63000c669a 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -276,6 +276,7 @@ void ASTTypeWriter::VisitFunctionType(const FunctionType *T) { Record.push_back(C.getCC()); Record.push_back(C.getProducesResult()); Record.push_back(C.getNoCallerSavedRegs()); + Record.push_back(C.getNoCfCheck()); if (C.getHasRegParm() || C.getRegParm() || C.getProducesResult()) AbbrevToUse = 0; @@ -884,6 +885,7 @@ void ASTWriter::WriteTypeAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // CC Abv->Add(BitCodeAbbrevOp(0)); // ProducesResult Abv->Add(BitCodeAbbrevOp(0)); // NoCallerSavedRegs + Abv->Add(BitCodeAbbrevOp(0)); // NoCfCheck // FunctionProtoType Abv->Add(BitCodeAbbrevOp(0)); // IsVariadic Abv->Add(BitCodeAbbrevOp(0)); // HasTrailingReturn |