diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index aa582da916053e7d9632bc06e896a5e4a6452dbf..97111056cd46162fcb31800480e2e8efcc9b1f3c 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2867,6 +2867,14 @@ public: static constexpr ADLCallKind NotADL = ADLCallKind::NotADL; static constexpr ADLCallKind UsesADL = ADLCallKind::UsesADL; + void setPreferInlineScopeSpecifier(PreferInlineScopeSpecifier PreferInlineSpec) { + CallExprBits.PreferInlineSpecifier = PreferInlineSpec; + } + + PreferInlineScopeSpecifier getPreferInlineScopeSpecifier() const { + return (PreferInlineScopeSpecifier) CallExprBits.PreferInlineSpecifier; + } + protected: /// Build a call expression, assuming that appropriate storage has been /// allocated for the trailing objects. diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 87a4951ebf9c1aaf7654f06b005efee6bcd5c871..43a662dc879e9b51c05894ad329383090e81b08e 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -470,9 +470,10 @@ protected: /// True if the call expression has some floating-point features. unsigned HasFPFeatures : 1; - /// Padding used to align OffsetToTrailingObjects to a byte multiple. - unsigned : 24 - 3 - NumExprBits; + uint64_t PreferInlineSpecifier : 2; + /// Padding used to align OffsetToTrailingObjects to a byte multiple. + unsigned : 24 - 5 - NumExprBits; /// The offset in bytes from the this pointer to the start of the /// trailing objects belonging to CallExpr. Intentionally byte sized /// for faster access. diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index a0a87b0fe1612a24df7d484dc21581809cc1925a..836e13cbb218c5a38ccf8e458849f9283e4ff672 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4127,3 +4127,8 @@ def ReturnsByteCountIndex : InheritableAttr { let InheritEvenIfAlreadyPresent = 1; let TemplateDependent = 1; } +def FunctionLikeMacro : InheritableAttr { + let Spellings = [GNU<"function_like_macro">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; +} \ No newline at end of file diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index a204e13351f84baf3300a7f75769099ca0bad05f..5c64e855dad986d38605c15e8a8c356a420b1a27 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1609,7 +1609,11 @@ def err_unknown_hlsl_semantic : Error<"unknown HLSL semantic %0">; def ext_hlsl_access_specifiers : ExtWarn< "access specifiers are a clang HLSL extension">, InGroup; - + +def warn_pragma_prefer_inline : Warning< + "incorrect use of '#pragma prefer_inline on|off' - ignored">, + InGroup; + // BSC Parser Diagnostics def invalid_param_for_trait_member : Error<"the first parameter of trait member function must be 'This* this'">; def err_unexpected_token_for_impl_trait_decl : Error<"unexpected token for ImplTraitDecl">; diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index b21e8c8a3e391800d29959786cfa2fcf6334e274..76fe2f7deacb65734cf2c025a332e96b5b7ceb2a 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -398,6 +398,12 @@ namespace clang { SS_Safe = 1, SS_Unsafe = 2, }; + + enum PreferInlineScopeSpecifier { + PI_None = 0, + PI_PreferInline = 1, + PI_PreferNoInline = 2, + }; } // end namespace clang #endif // LLVM_CLANG_BASIC_SPECIFIERS_H diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 2dfe2c44eb98fe48a9604b01de6d60d1e8b4075e..3a5b123482a2130dba65be359ad39e6128a912c5 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -810,6 +810,11 @@ PRAGMA_ANNOTATION(pragma_unused) // handles #pragma SAFE ... directives. PRAGMA_ANNOTATION(pragma_safe) +// Annotations for pragma prefer_inline (ON/OFF) +// The lexer produces these so that they only take effect when the parser +// handles #pragma prefer_inline ... directives. +PRAGMA_ANNOTATION(pragma_prefer_inline) + // Annotation for #pragma GCC visibility... // The lexer produces these so that they only take effect when the parser // handles them. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 2338a5f3910534e24b08ad92cafd4027f0d8ee47..eb33ca7d9b089389351cd79f907e702ee374720a 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1126,6 +1126,8 @@ def fPIC : Flag<["-"], "fPIC">, Group; def fno_PIC : Flag<["-"], "fno-PIC">, Group; def fPIE : Flag<["-"], "fPIE">, Group; def fno_PIE : Flag<["-"], "fno-PIE">, Group; +def opt_string : Joined<["-"], "opt-string=">, Flags<[CC1Option]>, + MarshallingInfoString>; defm access_control : BoolFOption<"access-control", LangOpts<"AccessControl">, DefaultTrue, NegFlag, diff --git a/clang/include/clang/Lex/PreprocessorOptions.h b/clang/include/clang/Lex/PreprocessorOptions.h index 4cf18e98f051f2e3717b5d8823565b8f9a7fc31d..d22442723c5761e3be2667a2244e777a21ca3b1e 100644 --- a/clang/include/clang/Lex/PreprocessorOptions.h +++ b/clang/include/clang/Lex/PreprocessorOptions.h @@ -96,6 +96,9 @@ public: /// The implicit PCH included at the start of the translation unit, or empty. std::string ImplicitPCHInclude; + /// Opt string for lto + std::string OptString; + /// Headers that will be converted to chained PCHs in memory. std::vector ChainedIncludes; @@ -251,6 +254,7 @@ public: ChainedIncludes.clear(); DumpDeserializedPCHDecls = false; ImplicitPCHInclude.clear(); + OptString.clear(); SingleFileParseMode = false; LexEditorPlaceholders = true; RetainRemappedFileBuffers = true; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 57c80ec6c275f459bd5baa5e53540f64395820aa..b0ca13127dcd554ff5ac8853f7fdf1f6e738f18a 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -217,6 +217,7 @@ class Parser : public CodeCompletionHandler { std::unique_ptr MaxTokensTotalPragmaHandler; std::unique_ptr RISCVPragmaHandler; std::unique_ptr SafeHandler; + std::unique_ptr PreferInlineHandler; std::unique_ptr CommentSemaHandler; @@ -296,6 +297,11 @@ class Parser : public CodeCompletionHandler { } void DestroyTemplateIds(); + /// Reset "#pragma prefer_inline ON/OFF" + void ResetPreferInlineScopeToNone() { + Actions.SetPragmaPreferInlineInfo(PI_None); + } + /// RAII object to destroy TemplateIdAnnotations where possible, from a /// likely-good position during parsing. struct DestroyTemplateIdAnnotationsRAIIObj { @@ -792,6 +798,7 @@ private: void HandlePragmaAttribute(); void HandlePragmaSafe(); + void HandlePragmaPreferInline(); /// GetLookAheadToken - This peeks ahead N tokens and returns that token /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7904559b25d9fd3f79e83a9a97c74addb2dd7a25..b779c16fc4dd7cbeac912ae5f7f6cb6251e47ac9 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4921,6 +4921,7 @@ public: private: SafeScopeSpecifier PragmaSafeInfo = SS_None; + PreferInlineScopeSpecifier PragmaPreferInlineInfo = PI_None; public: enum PragmaSafeStatus { @@ -4938,6 +4939,21 @@ public: PragmaSafeInfo = SafeSpec; } + + enum PragmaPreferInlineStatus { + PPI_On, + PPI_Off, + }; + + void ActOnPragmaPreferInline(PragmaPreferInlineStatus St); + + PreferInlineScopeSpecifier GetPragmaPreferInlineInfo() { + return PragmaPreferInlineInfo; + } + + void SetPragmaPreferInlineInfo(PreferInlineScopeSpecifier PreferInlineSpec) { + PragmaPreferInlineInfo = PreferInlineSpec; + } /// A RAII object to enter scope of a compound statement. class CompoundScopeRAII { public: diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 4963177b62ea67de58be72fb0c2e4d4de6612a7b..ccfe9f9cfa6fcc472ca3fb728229f54717c83985 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -363,6 +363,9 @@ enum ControlRecordTypes { /// Record code for the module build directory. MODULE_DIRECTORY, + + /// Recode code for the bishengc lto opt string + OPT_STRING, }; /// Record types that occur within the options block inside diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index f4be484bc0a9fa09e6e687bff4ca3da90a29f92d..149acc6f5d1342c33dfcbb6939d5bc66da018683 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1379,6 +1379,8 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef PreArgs, CallExprBits.HasFPFeatures = FPFeatures.requiresTrailingStorage(); if (hasStoredFPFeatures()) setStoredFPFeatures(FPFeatures); + + CallExprBits.PreferInlineSpecifier = PI_None; } CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs, diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 0796d55b81e7152c8792922066aa4e78cde4c823..c1fc4bba8ce2276107ed1e2e3e5009b0e617dea6 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1004,6 +1004,11 @@ void TextNodeDumper::VisitCallExpr(const CallExpr *Node) { OS << " adl"; if (Node->hasStoredFPFeatures()) printFPOptions(Node->getFPFeatures()); + if (Node->getPreferInlineScopeSpecifier() == PI_PreferInline) { + OS << " prefer_inline"; + } else if (Node->getPreferInlineScopeSpecifier() == PI_PreferNoInline) { + OS << " prefer_no_inline"; + } } void TextNodeDumper::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node) { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 69b63800f57347ffa65b577f8540194756bc5c7e..031354a4fab043212f206a95492d4c71f26d455c 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4794,6 +4794,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.getLastArg(options::OPT_save_temps_EQ)) Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ); + if (Args.getLastArg(options::OPT_opt_string)) + Args.AddLastArg(CmdArgs, options::OPT_opt_string); + auto *MemProfArg = Args.getLastArg(options::OPT_fmemory_profile, options::OPT_fmemory_profile_EQ, options::OPT_fno_memory_profile); diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 7a1c87d30be4b4582a84ab20ca16b8436e497bfa..6df31ee9b714dcb4f3fac3c22ec894ff248be249 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -344,6 +344,12 @@ struct PragmaSafeHandler : public PragmaHandler { Token &FirstToken) override; }; +struct PragmaPreferInlineHandler : public PragmaHandler { + PragmaPreferInlineHandler() : PragmaHandler("prefer_inline") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, + Token &FirstToken) override; +}; + struct PragmaMaxTokensHereHandler : public PragmaHandler { PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {} void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, @@ -517,6 +523,9 @@ void Parser::initializePragmaHandlers() { SafeHandler.reset(new PragmaSafeHandler()); PP.AddPragmaHandler(SafeHandler.get()); + + PreferInlineHandler.reset(new PragmaPreferInlineHandler()); + PP.AddPragmaHandler(PreferInlineHandler.get()); } void Parser::resetPragmaHandlers() { @@ -649,6 +658,9 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler(SafeHandler.get()); SafeHandler.reset(); + + PP.RemovePragmaHandler(PreferInlineHandler.get()); + PreferInlineHandler.reset(); } /// Handle the annotation token produced for #pragma unused(...) @@ -1916,6 +1928,14 @@ void Parser::HandlePragmaSafe() { Actions.ActOnPragmaSafe(St); } +void Parser::HandlePragmaPreferInline() { + assert(Tok.is(tok::annot_pragma_prefer_inline)); + Sema::PragmaPreferInlineStatus St = static_cast( + reinterpret_cast(Tok.getAnnotationValue())); + (void)ConsumeAnnotationToken(); + Actions.ActOnPragmaPreferInline(St); +} + // #pragma GCC visibility comes in two variants: // 'push' '(' [visibility] ')' // 'pop' @@ -3940,6 +3960,46 @@ void PragmaSafeHandler::HandlePragma(Preprocessor &PP, PragmaIntroducer Introduc PP.EnterTokenStream(Toks, true, false); } +// #pragma prefer_inline ON +// #pragma prefer_inline OFF +void PragmaPreferInlineHandler::HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, Token &PPITok) { + Sema::PragmaPreferInlineStatus St = Sema::PPI_On; + + Token Tok; + PP.Lex(Tok); + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_prefer_inline); + return; + } + SourceLocation EndLoc = Tok.getLocation(); + const IdentifierInfo *II = Tok.getIdentifierInfo(); + if (II->isStr("ON")) { + St = Sema::PPI_On; + PP.Lex(Tok); + } + else if (II->isStr("OFF")) { + St = Sema::PPI_Off; + PP.Lex(Tok); + } else { + PP.Diag(Tok.getLocation(), diag::warn_pragma_prefer_inline); + return; + } + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_prefer_inline); + return; + } + + MutableArrayRef Toks(PP.getPreprocessorAllocator().Allocate(1), 1); + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_prefer_inline); + Toks[0].setLocation(PPITok.getLocation()); + Toks[0].setAnnotationEndLoc(EndLoc); + Toks[0].setAnnotationValue(reinterpret_cast( + static_cast(St))); + PP.EnterTokenStream(Toks, true, false); +} + // Handle '#pragma clang max_tokens 12345'. void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 6dcb9539db10247e952ff2e3c282a5eab3179180..d18ccad24a9a0e9b26c52717715ee391a77186e7 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -984,6 +984,8 @@ StmtResult Parser::ParseCompoundStatement(bool isStmtExpr, SafeLoc = ConsumeToken(); } + ResetPreferInlineScopeToNone(); + assert(Tok.is(tok::l_brace) && "Not a compount stmt!"); // Enter a scope to hold everything within the compound stmt. Compound @@ -1056,6 +1058,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_safe: HandlePragmaSafe(); break; + case tok::annot_pragma_prefer_inline: + HandlePragmaPreferInline(); + break; default: checkForPragmas = false; break; @@ -1186,6 +1191,9 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr, SafeScopeSpecifie StmtResult R; if (Tok.isNot(tok::kw___extension__)) { R = ParseStatementOrDeclaration(Stmts, SubStmtCtx); + if (Tok.isNot(tok::annot_pragma_prefer_inline) && R.get() != nullptr) { + ResetPreferInlineScopeToNone(); + } } else { // __extension__ can start declarations and it can also be a unary // operator for expressions. Consume multiple __extension__ markers here @@ -1533,6 +1541,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { /*MissingOK=*/false, &LParen, &RParen)) return StmtError(); + ResetPreferInlineScopeToNone(); + if (IsConstexpr) ConstexprCondition = Cond.getKnownValue(); } @@ -1625,6 +1635,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter); ElseStmt = ParseStatement(); + ResetPreferInlineScopeToNone(); + if (ElseStmt.isUsable()) MIChecker.Check(); @@ -1729,6 +1741,8 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { /*MissingOK=*/false, &LParen, &RParen)) return StmtError(); + ResetPreferInlineScopeToNone(); + StmtResult Switch = Actions.ActOnStartOfSwitchStmt( SwitchLoc, LParen, InitStmt.get(), Cond, RParen); @@ -1820,6 +1834,8 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { /*MissingOK=*/false, &LParen, &RParen)) return StmtError(); + ResetPreferInlineScopeToNone(); + // C99 6.8.5p5 - In C99, the body of the while statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this // if the body isn't a compound statement to avoid push/pop in common cases. @@ -1879,12 +1895,26 @@ StmtResult Parser::ParseDoStatement() { bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus; ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); + bool IsPreferInlineStatement = false; + PreferInlineScopeSpecifier PreferInlineState; + if (Actions.GetPragmaPreferInlineInfo() != PI_None) { + IsPreferInlineStatement = true; + PreferInlineState = Actions.GetPragmaPreferInlineInfo(); + Actions.SetPragmaPreferInlineInfo(PI_None); + } + // Read the body statement. StmtResult Body(ParseStatement()); // Pop the body scope if needed. InnerScope.Exit(); + ResetPreferInlineScopeToNone(); + + if (IsPreferInlineStatement) { + Actions.SetPragmaPreferInlineInfo(PreferInlineState); + } + if (Tok.isNot(tok::kw_while)) { if (!Body.isInvalid()) { Diag(Tok, diag::err_expected_while); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index cabbe67a1cbdeb928c02783b1d5a7958faad3efc..12cdf4f6e0fcdefc59051fe408be7f88bb74c1d7 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -8679,6 +8679,10 @@ static void handleReturnsCountIndexFuncPtr(Sema &S, Decl *D, const ParsedAttr &A D->addAttr(::new (S.Context) ReturnsCountIndexAttr(S.Context, AL, LenVarIdx)); } +static void handleFunctionLikeMacro(Sema &S, Decl *D, const ParsedAttr &Attrs) { + D->addAttr(::new (S.Context) FunctionLikeMacroAttr(S.Context, Attrs)); +} + //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -9538,6 +9542,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, else handleReturnsCountIndexAttr(S, D, AL, true); break; + case ParsedAttr::AT_FunctionLikeMacro: + handleFunctionLikeMacro(S, D, AL); + break; } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d150b95e507abc724af854168f4f4e9fdb7fe46d..23a816717ef3039db5958cacce60ad67ba328a8d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6788,6 +6788,11 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, if (CE) DiagnosedUnqualifiedCallsToStdFunctions(*this, CE); } + CallExpr *CE = dyn_cast(Call.get()); + if (CE) { + PreferInlineScopeSpecifier CallExprSpec = GetPragmaPreferInlineInfo(); + CE->setPreferInlineScopeSpecifier(CallExprSpec); + } return Call; } diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index aad4be0165c185fe15f94ec6ac35b27c70bff09c..b3fb666b4e6a4a8535d12b0f2edd79166719d97b 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -461,6 +461,16 @@ void Sema::ActOnPragmaSafe(PragmaSafeStatus St) { SetPragmaSafeInfo(spec); } +void Sema::ActOnPragmaPreferInline(PragmaPreferInlineStatus St) { + PreferInlineScopeSpecifier spec = PI_None; + if (St == PSS_On) { + spec = PI_PreferInline; + } else if (St == PSS_Off) { + spec = PI_PreferNoInline; + } + SetPragmaPreferInlineInfo(spec); +} + ExprResult Sema::ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val) { if (!Val.get()) diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 6b82e2f7afc2151bac00a498ec9ec6a41fb27d98..f5f10b12f883a2e8ca49495a928df9919f71f45b 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2989,6 +2989,9 @@ ASTReader::ReadControlBlock(ModuleFile &F, F.InputFilesLoaded.resize(NumInputs); F.NumUserInputFiles = NumUserInputs; break; + + case OPT_STRING: + break; } } } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 8f08c5994d7eb7b997a9e235589bc161b133077e..484e84ddfb63422f3e1885c4dce687aae8c99bec 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1013,6 +1013,7 @@ void ASTStmtReader::VisitCallExpr(CallExpr *E) { if (HasFPFeatures) E->setStoredFPFeatures( FPOptionsOverride::getFromOpaqueInt(Record.readInt())); + E->setPreferInlineScopeSpecifier(static_cast(Record.readInt())); } void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index c6be8c29f6c684c6c2744aaca8462fc4732179d3..21e95ea36b623979a61aef9848b6b6e85f784615 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -785,6 +785,7 @@ void ASTWriter::WriteBlockInfoBlock() { // Control Block. BLOCK(CONTROL_BLOCK); + RECORD(OPT_STRING); RECORD(METADATA); RECORD(MODULE_NAME); RECORD(MODULE_DIRECTORY); @@ -1199,6 +1200,18 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Stream.EnterSubblock(CONTROL_BLOCK_ID, 5); RecordData Record; + // add lto opt string + std::string OptString = PP.getPreprocessorOpts().OptString; + if (!OptString.empty()) { + OptString = OptString + '\0'; + auto Abbrev = std::make_shared(); + Abbrev->Add(BitCodeAbbrevOp(OPT_STRING)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); + Record = {OPT_STRING}; + Stream.EmitRecordWithBlob(AbbrevCode, Record, OptString); + Record.clear(); + } // Metadata auto MetadataAbbrev = std::make_shared(); MetadataAbbrev->Add(BitCodeAbbrevOp(METADATA)); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index e47ce0c2637309620bee3ee9ab9b043332fa38d2..e38e3b006cec4a7615577feb965441fb5b9356f8 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -873,6 +873,7 @@ void ASTStmtWriter::VisitCallExpr(CallExpr *E) { if (E->hasStoredFPFeatures()) Record.push_back(E->getFPFeatures().getAsOpaqueInt()); Code = serialization::EXPR_CALL; + Record.push_back(E->getPreferInlineScopeSpecifier()); } void ASTStmtWriter::VisitRecoveryExpr(RecoveryExpr *E) {