diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Parse/ParsePragma.cpp | 53 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaAttr.cpp | 28 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 13 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 11 |
5 files changed, 110 insertions, 0 deletions
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 133c0e028f5..787d3f0bdf4 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -131,6 +131,16 @@ struct PragmaMSPragma : public PragmaHandler { Token &FirstToken) override; }; +/// PragmaOptimizeHandler - "\#pragma clang optimize on/off". +struct PragmaOptimizeHandler : public PragmaHandler { + PragmaOptimizeHandler(Sema &S) + : PragmaHandler("optimize"), Actions(S) {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +private: + Sema &Actions; +}; + } // end namespace void Parser::initializePragmaHandlers() { @@ -195,6 +205,9 @@ void Parser::initializePragmaHandlers() { MSSection.reset(new PragmaMSPragma("section")); PP.AddPragmaHandler(MSSection.get()); } + + OptimizeHandler.reset(new PragmaOptimizeHandler(Actions)); + PP.AddPragmaHandler("clang", OptimizeHandler.get()); } void Parser::resetPragmaHandlers() { @@ -249,6 +262,9 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler("STDC", FPContractHandler.get()); FPContractHandler.reset(); + + PP.RemovePragmaHandler("clang", OptimizeHandler.get()); + OptimizeHandler.reset(); } /// \brief Handle the annotation token produced for #pragma unused(...) @@ -1531,3 +1547,40 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP, Actions.ActOnPragmaMSComment(Kind, ArgumentString); } + +// #pragma clang optimize off +// #pragma clang optimize on +void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &FirstToken) { + Token Tok; + PP.Lex(Tok); + if (Tok.is(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_missing_argument); + return; + } + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) + << PP.getSpelling(Tok); + return; + } + const IdentifierInfo *II = Tok.getIdentifierInfo(); + // The only accepted values are 'on' or 'off'. + bool IsOn = false; + if (II->isStr("on")) { + IsOn = true; + } else if (!II->isStr("off")) { + PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) + << PP.getSpelling(Tok); + return; + } + PP.Lex(Tok); + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument) + << PP.getSpelling(Tok); + return; + } + + Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation()); +} diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index bb25be7da17..6397487981b 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -470,6 +470,34 @@ void Sema::AddCFAuditedAttribute(Decl *D) { D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc)); } +void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) { + if(On) + OptimizeOffPragmaLocation = SourceLocation(); + else + OptimizeOffPragmaLocation = PragmaLoc; +} + +void Sema::AddRangeBasedOptnone(FunctionDecl *FD) { + // In the future, check other pragmas if they're implemented (e.g. pragma + // optimize 0 will probably map to this functionality too). + if(OptimizeOffPragmaLocation.isValid()) + AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation); +} + +void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, + SourceLocation Loc) { + // Don't add a conflicting attribute. No diagnostic is needed. + if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>()) + return; + + // Add attributes only if required. Optnone requires noinline as well, but if + // either is already present then don't bother adding them. + if (!FD->hasAttr<OptimizeNoneAttr>()) + FD->addAttr(OptimizeNoneAttr::CreateImplicit(Context, Loc)); + if (!FD->hasAttr<NoInlineAttr>()) + FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc)); +} + typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack; enum : unsigned { NoVisibility = ~0U }; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a3dd2e7462c..a522ef4784b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7373,6 +7373,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // marking the function. AddCFAuditedAttribute(NewFD); + // If this is a function definition, check if we have to apply optnone due to + // a pragma. + if(D.isFunctionDefinition()) + AddRangeBasedOptnone(NewFD); + // If this is the first declaration of an extern C variable, update // the map of such variables. if (NewFD->isFirstDecl() && !NewFD->isInvalidDecl() && diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 143a7386ff2..4ea95d07120 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3281,6 +3281,14 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { LateParsedTemplates.append(Record.begin(), Record.end()); break; } + + case OPTIMIZE_PRAGMA_OPTIONS: + if (Record.size() != 1) { + Error("invalid pragma optimize record"); + return Failure; + } + OptimizeOffPragmaLocation = ReadSourceLocation(F, Record[0]); + break; } } } @@ -6808,6 +6816,11 @@ void ASTReader::UpdateSema() { } SemaDeclRefs.clear(); } + + // Update the state of 'pragma clang optimize'. Use the same API as if we had + // encountered the pragma in the source. + if(OptimizeOffPragmaLocation.isValid()) + SemaObj->ActOnPragmaOptimize(/* IsOn = */ false, OptimizeOffPragmaLocation); } IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 7753986d58f..35da82c6e4c 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -866,6 +866,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(MACRO_OFFSET); RECORD(MACRO_TABLE); RECORD(LATE_PARSED_TEMPLATE); + RECORD(OPTIMIZE_PRAGMA_OPTIONS); // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); @@ -3850,6 +3851,14 @@ void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) { Stream.EmitRecord(LATE_PARSED_TEMPLATE, Record); } +/// \brief Write the state of 'pragma clang optimize' at the end of the module. +void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) { + RecordData Record; + SourceLocation PragmaLoc = SemaRef.getOptimizeOffPragmaLocation(); + AddSourceLocation(PragmaLoc, Record); + Stream.EmitRecord(OPTIMIZE_PRAGMA_OPTIONS, Record); +} + //===----------------------------------------------------------------------===// // General Serialization Routines //===----------------------------------------------------------------------===// @@ -4466,6 +4475,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, WriteMergedDecls(); WriteObjCCategories(); WriteLateParsedTemplates(SemaRef); + if(!WritingModule) + WriteOptimizePragmaOptions(SemaRef); // Some simple statistics Record.clear(); |

