diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 58ba43559e0ef5170366de6aefd5eb2a4ac32f15..5d627c5fb8f189af73ed85f6916d1ca93e11d17c 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1959,6 +1959,10 @@ public: this->ExtendedType = ExtendedType; } + /// Returns the start sourcelocation of extended type in BSCMethodDecl. + SourceLocation getExtentedTypeBeginLoc() { return BLoc; } + void setExtentedTypeBeginLoc(SourceLocation L) { BLoc = L; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == BSCMethod; } @@ -1966,6 +1970,7 @@ public: private: QualType ExtendedType; bool HasThisParam = false; + SourceLocation BLoc; }; /// Represents a static or instance method of a struct/union/class. diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index c327014732ef9cc96d2ec1e0588e3f2e90c77003..e5cd51081146232ce24a9e821ad856320e0d0a9f 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -137,8 +137,14 @@ protected: friend class ASTImporter; // Sets dependence dircetly. friend class ASTStmtReader; // Sets dependence dircetly. + SourceLocation EBLoc; + public: bool HasBSCScopeSpec = false; + + SourceLocation getExtendedTypeBeginLoc() { return EBLoc; } + void setExtendedTypeBeginLoc(SourceLocation L) { EBLoc = L; } + QualType getType() const { return TR; } void setType(QualType t) { // In C++, the type of an expression is always adjusted so that it diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index ad13f923fb6389f516fdfe50fa95f26fd996d0de..dbbe81b56107d58734b3e6dbeba014d520fef4ca 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -536,4 +536,8 @@ def err_drv_invalid_object_mode : Error<"OBJECT_MODE setting %0 is not recognize def err_aix_default_altivec_abi : Error< "The default Altivec ABI on AIX is not yet supported, use '-mabi=vec-extabi' for the extended Altivec ABI">; + +def warn_target_unsupported_non_bsc_file : Warning< + "ignoring '-rewrite-bsc' option because rewriting input type '%0' is not supported">, + InGroup; } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 817798926650f0b368b14725011bc904f02df77b..2892963b0685a6ffc3e498f370dd6270070e06f6 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3448,6 +3448,8 @@ def read__only__relocs : Separate<["-"], "read_only_relocs">; def remap : Flag<["-"], "remap">; def rewrite_objc : Flag<["-"], "rewrite-objc">, Flags<[NoXarchOption,CC1Option]>, HelpText<"Rewrite Objective-C source to C++">, Group; +def rewrite_bsc : Flag<["-"], "rewrite-bsc">, Flags<[CC1Option]>, Group, + HelpText<"Rewrite BSC source to C">; def rewrite_legacy_objc : Flag<["-"], "rewrite-legacy-objc">, Flags<[NoXarchOption]>, HelpText<"Rewrite Legacy Objective-C source to C++">; def rdynamic : Flag<["-"], "rdynamic">, Group; diff --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def index cc8ccab1ee7b4062d5e0b0ce6ff658739ddae8b4..1e0fc97880640204d9d2eb704d4d72c8ac078414 100644 --- a/clang/include/clang/Driver/Types.def +++ b/clang/include/clang/Driver/Types.def @@ -47,6 +47,7 @@ TYPE("hip", HIP_DEVICE, PP_HIP, "cu", phases TYPE("bsc", BSC, PP_C, "cbs", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("objc-cpp-output", PP_ObjC_Alias, INVALID, "mi", phases::Compile, phases::Backend, phases::Assemble, phases::Link) +TYPE("bsc-cpp-output", PP_BSCXX, INVALID, "ii", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("objective-c", ObjC, PP_ObjC, "m", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("c++-cpp-output", PP_CXX, INVALID, "ii", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("c++", CXX, PP_CXX, "cpp", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link) @@ -92,6 +93,7 @@ TYPE("pcm", ModuleFile, INVALID, "pcm", phases TYPE("plist", Plist, INVALID, "plist", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("rewritten-legacy-objc", RewrittenLegacyObjC,INVALID, "cpp", phases::Compile, phases::Backend, phases::Assemble, phases::Link) +TYPE("rewritten-bsc", RewrittenBSC, INVALID, "c", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("remap", Remap, INVALID, "remap", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("precompiled-header", PCH, INVALID, "gch", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("object", Object, INVALID, "o", phases::Link) diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 223c1e05d0539acf104027db58e5f6d844f03d63..e3623e7b438b741fe99a3fc7ee2f7ba556561892 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -119,6 +119,9 @@ enum ActionKind { /// ObjC->C Rewriter. RewriteObjC, + /// BSC->C Rewriter. + RewriteBSC, + /// Rewriter playground RewriteTest, diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 9e800892644710a8c1359772ca46d596bcbb3dfc..93d5a1da2d38bc6dfcf40c0564d0a3824c09ae33 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1791,13 +1791,11 @@ private: CastParseKind ParseKind, bool isAddressOfOperand, bool &NotCastExpr, TypeCastState isTypeCast, bool isVectorLiteral = false, bool *NotPrimaryExpression = nullptr, bool HasBSCScopeSpec = false); - ExprResult ParseCastExpression(CastParseKind ParseKind, - bool isAddressOfOperand, bool &NotCastExpr, - TypeCastState isTypeCast, - bool isVectorLiteral = false, - bool *NotPrimaryExpression = nullptr, - QualType T = QualType(), - bool HasBSCScopeSpec = false); + ExprResult ParseCastExpression( + CastParseKind ParseKind, bool isAddressOfOperand, bool &NotCastExpr, + TypeCastState isTypeCast, bool isVectorLiteral = false, + bool *NotPrimaryExpression = nullptr, QualType T = QualType(), + bool HasBSCScopeSpec = false, SourceLocation BL = SourceLocation()); ExprResult ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand = false, TypeCastState isTypeCast = NotTypeCast, diff --git a/clang/include/clang/Parse/RAIIObjectsForParser.h b/clang/include/clang/Parse/RAIIObjectsForParser.h index 7f8040d78b90337143160ecfe58f2d9e0c13bb4e..bc1754614ad93a70ab8f9dd7f49e5aa45316441b 100644 --- a/clang/include/clang/Parse/RAIIObjectsForParser.h +++ b/clang/include/clang/Parse/RAIIObjectsForParser.h @@ -196,26 +196,6 @@ namespace clang { } }; - // BSC - class BSCScopeSpec : public DeclSpec { - ParsingDeclRAIIObject ParsingRAII; - - public: - BSCScopeSpec(Parser &P) - : DeclSpec(P.getAttrFactory()), - ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {} - BSCScopeSpec(Parser &P, ParsingDeclRAIIObject *RAII) - : DeclSpec(P.getAttrFactory()), ParsingRAII(P, RAII) {} - - const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const { - return ParsingRAII.getDelayedDiagnosticPool(); - } - - void complete(Decl *D) { ParsingRAII.complete(D); } - - void abort() { ParsingRAII.abort(); } - }; - /// A class for parsing a declarator. class ParsingDeclarator : public Declarator { ParsingDeclRAIIObject ParsingRAII; diff --git a/clang/include/clang/Rewrite/Frontend/ASTConsumers.h b/clang/include/clang/Rewrite/Frontend/ASTConsumers.h index 618b38050dc7c93465f46b27d479389b81e048fe..88158652f56d2942e0bbba7f2457cba508d56b80 100644 --- a/clang/include/clang/Rewrite/Frontend/ASTConsumers.h +++ b/clang/include/clang/Rewrite/Frontend/ASTConsumers.h @@ -36,6 +36,12 @@ CreateModernObjCRewriter(const std::string &InFile, DiagnosticsEngine &Diags, const LangOptions &LOpts, bool SilenceRewriteMacroWarning, bool LineInfo); +// BSC rewriter: attempts to rewrite BSC constructs into pure C code. +std::unique_ptr CreateBSCRewriter(const std::string &InFile, + std::unique_ptr OS, + DiagnosticsEngine &Diags, + const LangOptions &LOpts); + /// CreateHTMLPrinter - Create an AST consumer which rewrites source code to /// HTML with syntax highlighting suitable for viewing in a web-browser. std::unique_ptr CreateHTMLPrinter(std::unique_ptr OS, diff --git a/clang/include/clang/Rewrite/Frontend/FrontendActions.h b/clang/include/clang/Rewrite/Frontend/FrontendActions.h index 4e9d1941bce083c4c3934e8c78aea2677dea7f50..5013aca1bacf0085494b17d084fed8bbb5e1a97b 100644 --- a/clang/include/clang/Rewrite/Frontend/FrontendActions.h +++ b/clang/include/clang/Rewrite/Frontend/FrontendActions.h @@ -62,6 +62,12 @@ protected: StringRef InFile) override; }; +class RewriteBSCAction : public ASTFrontendAction { +protected: + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; +}; + class RewriteMacrosAction : public PreprocessorFrontendAction { protected: void ExecuteAction() override; diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index f57c94ff35a399cb927af476122b2abcf1bf9cd2..439008dff0fbb857300122d9df18f63bdb74968c 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -38,7 +38,6 @@ namespace clang { class ASTContext; - class BSCScopeSpec; class CXXRecordDecl; class TypeLoc; class LangOptions; @@ -223,6 +222,33 @@ public: unsigned location_size() const { return Builder.getBuffer().second; } }; +/// Represents a BSC typename-specifier. +/// +/// These can be in 2 states: +/// 1) Not present, identified by isEmpty() +/// 2) Present, identified by isNotEmpty() +class BSCScopeSpec { +private: + QualType ExtendedType; + SourceLocation ExtendedTypeBLoc; + SourceRange Range; + +public: + /// Used to mark parameters that include 'this'. + bool HasThisParam = false; + + QualType getExtendedType() const { return ExtendedType; } + void setExtendedType(QualType ExtendedType) { + this->ExtendedType = ExtendedType; + } + + void setBeginLoc(SourceLocation Loc) { ExtendedTypeBLoc = Loc; } + SourceLocation getBeginLoc() const { return ExtendedTypeBLoc; } + + bool isEmpty() const { return getBeginLoc().isInvalid(); } + bool isNotEmpty() const { return !isEmpty(); } +}; + /// Captures information about "declaration specifiers". /// /// "Declaration specifiers" encompasses storage-class-specifiers, @@ -1824,8 +1850,7 @@ class Declarator { private: const DeclSpec &DS; CXXScopeSpec SS; - DeclSpec *BSCDS = nullptr; - QualType ExtendedType; // BSC only + BSCScopeSpec BSS; UnqualifiedId Name; SourceRange Range; @@ -1927,22 +1952,10 @@ public: ~Declarator() { clear(); } - // Used to mark parameters that include 'this'. - bool HasThisParam = false; /// getDeclSpec - Return the declaration-specifier that this declarator was /// declared with. const DeclSpec &getDeclSpec() const { return DS; } - /// getBSCScopeSpec - Return the BSCMethod declaration-specifier that this - /// declarator was declared with. - DeclSpec *getBSCScopeSpec() { return BSCDS; } - void setBSCScopeSpec(DeclSpec *ScopeSpec) { BSCDS = ScopeSpec; } - - QualType getExtendedType() const { return ExtendedType; } - void setExtendedType(QualType ExtendedType) { - this->ExtendedType = ExtendedType; - } - /// getMutableDeclSpec - Return a non-const version of the DeclSpec. This /// should be used with extreme care: declspecs can often be shared between /// multiple declarators, so mutating the DeclSpec affects all of the @@ -1959,6 +1972,11 @@ public: const CXXScopeSpec &getCXXScopeSpec() const { return SS; } CXXScopeSpec &getCXXScopeSpec() { return SS; } + /// getBSCScopeSpec - Return the BSCMethod declaration-specifier that this + /// declarator was declared with. + const BSCScopeSpec &getBSCScopeSpec() const { return BSS; } + BSCScopeSpec &getBSCScopeSpec() { return BSS; } + /// Retrieve the name specified by this declarator. UnqualifiedId &getName() { return Name; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index fd5ed2f95055ed22a930e7bc11fe8ef3d01a6dc2..03e9cc7e48fe69ccb5aa0fb8476e17fb99696c92 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2672,7 +2672,8 @@ public: void CheckMain(FunctionDecl *FD, const DeclSpec &D); void CheckMSVCRTEntryPoint(FunctionDecl *FD); QualType ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc, - bool AddToContextMap); + bool AddToContextMap, BSCScopeSpec &BSS, + DeclSpec &DS); Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition); void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D); diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 418e1d3e8ec993145fc140c76cca4295da06ba53..9e4650902e3cf1e8a77cafe1cadffa2bebacc7f6 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -307,6 +307,7 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) || (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) || (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) || + (PhaseArg = DAL.getLastArg(options::OPT_rewrite_bsc)) || (PhaseArg = DAL.getLastArg(options::OPT__migrate)) || (PhaseArg = DAL.getLastArg(options::OPT__analyze)) || (PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) { @@ -3411,6 +3412,20 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args, YcArg = nullptr; } + Arg *RewriteBSCArg = Args.getLastArg(options::OPT_rewrite_bsc); + if (RewriteBSCArg) { + for (auto &I : Inputs) { + types::ID InputType = I.first; + if (InputType != types::TY_BSC) { + Diag(clang::diag::warn_target_unsupported_non_bsc_file) + << types::getTypeName(InputType); + Args.eraseArg(options::OPT_rewrite_bsc); + RewriteBSCArg = nullptr; + break; + } + } + } + Arg *FinalPhaseArg; phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg); @@ -3817,6 +3832,9 @@ Action *Driver::ConstructPhaseAction( if (Args.hasArg(options::OPT_rewrite_legacy_objc)) return C.MakeAction(Input, types::TY_RewrittenLegacyObjC); + if (Args.hasArg(options::OPT_rewrite_bsc)) { + return C.MakeAction(Input, types::TY_RewrittenBSC); + } if (Args.hasArg(options::OPT__analyze)) return C.MakeAction(Input, types::TY_Plist); if (Args.hasArg(options::OPT__migrate)) @@ -4115,7 +4133,8 @@ class ToolSelector final { bool canCollapsePreprocessorAction() const { return !C.getArgs().hasArg(options::OPT_no_integrated_cpp) && !C.getArgs().hasArg(options::OPT_traditional_cpp) && !SaveTemps && - !C.getArgs().hasArg(options::OPT_rewrite_objc); + !C.getArgs().hasArg(options::OPT_rewrite_objc) && + !C.getArgs().hasArg(options::OPT_rewrite_bsc); } /// Struct that relates an action with the offload actions that would be diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1976b48e0f6a4aaab5c84358a99604d5c2b033ae..f5d4c656fd098c2695f58527144bca2e9bc0b9c1 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -715,6 +715,8 @@ static void addDashXForInput(const ArgList &Args, const InputInfo &Input, CmdArgs.push_back("-x"); if (Args.hasArg(options::OPT_rewrite_objc)) CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX)); + else if (Args.hasArg(options::OPT_rewrite_bsc)) + CmdArgs.push_back(types::getTypeName(types::TY_PP_BSCXX)); else { // Map the driver type to the frontend type. This is mostly an identity // mapping, except that the distinction between module interface units @@ -4263,7 +4265,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-Eonly"); else { CmdArgs.push_back("-E"); - if (Args.hasArg(options::OPT_rewrite_objc) && + if ((Args.hasArg(options::OPT_rewrite_objc) || + Args.hasArg(options::OPT_rewrite_bsc)) && !Args.hasArg(options::OPT_g_Group)) CmdArgs.push_back("-P"); } @@ -4317,6 +4320,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } else if (JA.getType() == types::TY_RewrittenLegacyObjC) { CmdArgs.push_back("-rewrite-objc"); rewriteKind = RK_Fragile; + } else if (JA.getType() == types::TY_RewrittenBSC) { + CmdArgs.push_back("-rewrite-bsc"); } else { assert(JA.getType() == types::TY_PP_Asm && "Unexpected output type!"); } diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp index 69f3c7d298ab81d1f02cc5617071a8da52993f18..bd08e05526d0ca86657cbe22ab89e157dcf4fdb1 100644 --- a/clang/lib/Driver/Types.cpp +++ b/clang/lib/Driver/Types.cpp @@ -101,9 +101,9 @@ bool types::canTypeBeUserSpecified(ID Id) { TY_PP_ObjCHeader, TY_PP_CXXHeader, TY_PP_ObjCXXHeader, TY_PP_CXXModule, TY_LTO_IR, TY_LTO_BC, TY_Plist, TY_RewrittenObjC, TY_RewrittenLegacyObjC, - TY_Remap, TY_PCH, TY_Object, - TY_Image, TY_dSYM, TY_Dependencies, - TY_CUDA_FATBIN, TY_HIP_FATBIN}; + TY_RewrittenBSC, TY_Remap, TY_PCH, + TY_Object, TY_Image, TY_dSYM, + TY_Dependencies, TY_CUDA_FATBIN, TY_HIP_FATBIN}; return !llvm::is_contained(kStaticLangageTypes, Id); } @@ -349,6 +349,7 @@ types::getCompilationPhases(const clang::driver::Driver &Driver, DAL.getLastArg(options::OPT_verify_pch) || DAL.getLastArg(options::OPT_rewrite_objc) || DAL.getLastArg(options::OPT_rewrite_legacy_objc) || + DAL.getLastArg(options::OPT_rewrite_bsc) || DAL.getLastArg(options::OPT__migrate) || DAL.getLastArg(options::OPT__analyze) || DAL.getLastArg(options::OPT_emit_ast)) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 402f5a5870525824e824444174b8e04638a4e08d..117459fdf671b9fb21c16496c8212730939911bb 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1594,6 +1594,9 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::EmitCodeGenOnly; break; case OPT_emit_obj: Opts.ProgramAction = frontend::EmitObj; break; + case OPT_rewrite_bsc: + Opts.ProgramAction = frontend::RewriteBSC; + break; case OPT_fixit_EQ: Opts.FixItSuffix = A->getValue(); LLVM_FALLTHROUGH; @@ -2740,6 +2743,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::PluginAction: case frontend::RewriteObjC: case frontend::RewriteTest: + case frontend::RewriteBSC: case frontend::RunAnalysis: case frontend::TemplightDump: case frontend::MigrateSource: diff --git a/clang/lib/Frontend/Rewrite/CMakeLists.txt b/clang/lib/Frontend/Rewrite/CMakeLists.txt index 64aa651394dff1a6602fb57fb1d4e2875b61b3f0..442dd8cfc81b4221382701ce6a0ce3e1e4050ef4 100644 --- a/clang/lib/Frontend/Rewrite/CMakeLists.txt +++ b/clang/lib/Frontend/Rewrite/CMakeLists.txt @@ -10,6 +10,7 @@ add_clang_library(clangRewriteFrontend RewriteMacros.cpp RewriteModernObjC.cpp RewriteObjC.cpp + RewriteBSC.cpp RewriteTest.cpp LINK_LIBS diff --git a/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/clang/lib/Frontend/Rewrite/FrontendActions.cpp index 5351ff0593edc86a9c73ca5e5df246edf7c12e6b..86342f8a5e7910d8b4c1421063130b11a9dc4dc9 100644 --- a/clang/lib/Frontend/Rewrite/FrontendActions.cpp +++ b/clang/lib/Frontend/Rewrite/FrontendActions.cpp @@ -178,6 +178,16 @@ RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { #endif +std::unique_ptr +RewriteBSCAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { + if (std::unique_ptr OS = + CI.createDefaultOutputFile(false, InFile, "c")) { + return CreateBSCRewriter(std::string(InFile), std::move(OS), + CI.getDiagnostics(), CI.getLangOpts()); + } + return nullptr; +} + //===----------------------------------------------------------------------===// // Preprocessor Actions //===----------------------------------------------------------------------===// diff --git a/clang/lib/Frontend/Rewrite/RewriteBSC.cpp b/clang/lib/Frontend/Rewrite/RewriteBSC.cpp new file mode 100644 index 0000000000000000000000000000000000000000..133757a322e73115efe57029a6cffa3ad225aab0 --- /dev/null +++ b/clang/lib/Frontend/Rewrite/RewriteBSC.cpp @@ -0,0 +1,258 @@ +//===--- RewriteBSC.cpp - Playground for the code rewriter ---------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Hacks and fun related to the code rewriter. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/AST.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "clang/Rewrite/Frontend/ASTConsumers.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +using namespace clang; + +namespace { +class RewriteBSC : public ASTConsumer { +private: + Rewriter Rewrite; + DiagnosticsEngine &Diags; + const LangOptions &LangOpts; + ASTContext *Context; + SourceManager *SM; + TranslationUnitDecl *TUDecl; + FileID MainFileID; + const char *MainFileStart, *MainFileEnd; + std::string InFileName; + std::unique_ptr OutFile; + + unsigned RewriteFailedDiag; + +public: + RewriteBSC(std::string inFile, std::unique_ptr OS, + DiagnosticsEngine &D, const LangOptions &LOpts); + ~RewriteBSC() override {} + + void Initialize(ASTContext &C) override; + + void HandleTranslationUnit(ASTContext &C) override; + bool HandleTopLevelDecl(DeclGroupRef D) override { + for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { + HandleTopLevelSingleDecl(*I); + } + return true; + } + void HandleTopLevelSingleDecl(Decl *D); + void HandleDeclInMainFile(Decl *D); + + void RewriteBSCMethodDecl(BSCMethodDecl *BMD); + void RewriteMemberExpr(MemberExpr *ME); + void RewriteCallExpr(CallExpr *CE); + void RewriteDeclRefExpr(DeclRefExpr *CE); + + void InsertText(SourceLocation Loc, StringRef Str, bool InsertAfter = true) { + // If insertion succeeded or warning disabled return with no warning. + if (!Rewrite.InsertText(Loc, Str, InsertAfter)) + return; + + Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); + } + + void ReplaceText(SourceLocation Start, unsigned OrigLength, StringRef Str) { + // If removal succeeded or warning disabled return with no warning. + if (!Rewrite.ReplaceText(Start, OrigLength, Str)) + return; + + Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag); + } +}; + +class RewriterVisitor : public StmtVisitor { +public: + RewriterVisitor(RewriteBSC *rewriter) : rewriter(rewriter) {} + RewriteBSC *rewriter; + + void VisitMemberExpr(MemberExpr *E) { + rewriter->RewriteMemberExpr(E); + VisitExpr(E); + } + + void VisitCallExpr(CallExpr *E) { + VisitExpr(E); + rewriter->RewriteCallExpr(E); + } + + void VisitDeclRefExpr(DeclRefExpr *DRE) { + VisitExpr(DRE); + rewriter->RewriteDeclRefExpr(DRE); + } + + void VisitStmt(Stmt *S) { + for (auto *C : S->children()) { + if (C) + Visit(C); + } + } +}; +} // end anonymous namespace + +RewriteBSC::RewriteBSC(std::string inFile, std::unique_ptr OS, + DiagnosticsEngine &D, const LangOptions &LOpts) + : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)) { + RewriteFailedDiag = Diags.getCustomDiagID( + DiagnosticsEngine::Warning, + "rewriting sub-expression within a macro (may not be correct)"); +} + +std::unique_ptr +clang::CreateBSCRewriter(const std::string &InFile, + std::unique_ptr OS, + DiagnosticsEngine &Diags, const LangOptions &LOpts) { + return std::make_unique(InFile, std::move(OS), Diags, LOpts); +} + +void RewriteBSC::Initialize(ASTContext &context) { + Context = &context; + SM = &Context->getSourceManager(); + TUDecl = Context->getTranslationUnitDecl(); + + // Get the ID and start/end of the main file. + MainFileID = SM->getMainFileID(); + llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID); + MainFileStart = MainBuf.getBufferStart(); + MainFileEnd = MainBuf.getBufferEnd(); + + Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts()); +} + +void RewriteBSC::HandleTopLevelSingleDecl(Decl *D) { + if (Diags.hasErrorOccurred()) + return; + + SourceLocation Loc = D->getLocation(); + Loc = SM->getExpansionLoc(Loc); + + // If this is for a builtin, ignore it. + if (Loc.isInvalid()) + return; + + // // If we have a decl in the main file, see if we should rewrite it. + if (SM->isWrittenInMainFile(Loc)) + return HandleDeclInMainFile(D); +} + +void RewriteBSC::HandleDeclInMainFile(Decl *D) { + switch (D->getKind()) { + case Decl::BSCMethod: + case Decl::Function: { + if (BSCMethodDecl *BSCMD = dyn_cast(D)) { + RewriteBSCMethodDecl(BSCMD); + } + FunctionDecl *FD = cast(D); + if (!FD->isThisDeclarationADefinition()) + break; + if (CompoundStmt *Body = dyn_cast_or_null(FD->getBody())) { + RewriterVisitor visitor(this); + visitor.VisitStmt(Body); + } + break; + } + default: + break; + } +} + +void RewriteBSC::HandleTranslationUnit(ASTContext &C) { + if (Diags.hasErrorOccurred()) + return; + + if (const RewriteBuffer *RewriteBuf = + Rewrite.getRewriteBufferFor(MainFileID)) { + *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); + } else { + // No change. + *OutFile << std::string(MainFileStart, MainFileEnd); + } + OutFile->flush(); +} + +std::string GetPrefix(QualType T) { + std::string ExtendedTypeStr = T.getAsString(); + for (int i = ExtendedTypeStr.length() - 1; i >= 0; i--) { + if (ExtendedTypeStr[i] == ' ') { + ExtendedTypeStr.replace(i, 1, "_"); + } + } + ExtendedTypeStr += "_"; + return ExtendedTypeStr; +} + +void RewriteBSC::RewriteBSCMethodDecl(BSCMethodDecl *BMD) { + SourceLocation StartLoc = BMD->getExtentedTypeBeginLoc(); + + DeclarationNameInfo DNI = BMD->getNameInfo(); + SourceLocation EndLoc = DNI.getBeginLoc(); + + const char *startBuf = SM->getCharacterData(StartLoc); + const char *endBuf = SM->getCharacterData(EndLoc); + + std::string ExtendedTypeStr = GetPrefix(BMD->getExtendedType()); + ReplaceText(StartLoc, endBuf - startBuf, ExtendedTypeStr); +} + +void RewriteBSC::RewriteCallExpr(CallExpr *CE) { + Expr *Callee = CE->getCallee(); + if (ImplicitCastExpr *ICE = dyn_cast(Callee)) { + Expr *SE = ICE->getSubExpr(); + if (MemberExpr *Member = dyn_cast(SE)) { + if (auto *BD = dyn_cast(Member->getMemberDecl())) { + std::string SStr; + llvm::raw_string_ostream Buf(SStr); + CE->getArg(0)->printPretty(Buf, nullptr, PrintingPolicy(LangOpts)); + const std::string &Str = Buf.str(); + SourceLocation StartLoc; + if (CE->getNumArgs() == 1) { + StartLoc = CE->getRParenLoc(); + InsertText(StartLoc, Str); + } else { + StartLoc = CE->getArg(1)->getBeginLoc(); + InsertText(StartLoc, Str + ", "); + } + } + } + } +} + +void RewriteBSC::RewriteMemberExpr(MemberExpr *ME) { + if (auto *BD = dyn_cast(ME->getMemberDecl())) { + SourceLocation LocStart = ME->getBeginLoc(); + SourceLocation MemberStart = ME->getMemberLoc(); + const char *startBuf = SM->getCharacterData(LocStart); + const char *endBuf = SM->getCharacterData(MemberStart); + std::string ExtendedTypeStr = GetPrefix(BD->getExtendedType()); + ReplaceText(LocStart, endBuf - startBuf, ExtendedTypeStr); + } +} + +void RewriteBSC::RewriteDeclRefExpr(DeclRefExpr *DRE) { + if (DRE->HasBSCScopeSpec) { + if (auto *BD = dyn_cast(DRE->getFoundDecl())) { + SourceLocation LocStart = DRE->getExtendedTypeBeginLoc(); + SourceLocation LocEnd = DRE->getBeginLoc(); + const char *startBuf = SM->getCharacterData(LocStart); + const char *endBuf = SM->getCharacterData(LocEnd); + std::string ExtendedTypeStr = GetPrefix(BD->getExtendedType()); + ReplaceText(LocStart, endBuf - startBuf, ExtendedTypeStr); + } + } +} diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index ac64e1708da6cdbf57a79c3cb138f5902e9637eb..25721a6f88a47a9efb25b38f153eea9bcbf4a6d3 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -108,6 +108,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) { #else case RewriteObjC: Action = "RewriteObjC"; break; #endif + case RewriteBSC: + return std::make_unique(); #if CLANG_ENABLE_ARCMT case MigrateSource: return std::make_unique(); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 4f5315c176f71ae54b74aef01fad9c5698b2d46c..dd64ded3f2a357bc675403606b30a19d484e95d6 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5714,12 +5714,14 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // BSC if (getLangOpts().BSC && FindUntil(tok::coloncolon) && Tok.isNot(tok::star)) { - BSCScopeSpec BSS(*this); - ParseBSCScopeSpecifiers(BSS); + DeclSpec DS(AttrFactory); + ParseBSCScopeSpecifiers(DS); TryConsumeToken(tok::coloncolon); - D.setBSCScopeSpec(&BSS); - Actions.ConvertBSCScopeSpecToType(D, BSS.getBeginLoc(), true); + BSCScopeSpec BSS; + BSS.setBeginLoc(DS.getBeginLoc()); + Actions.ConvertBSCScopeSpecToType(D, DS.getBeginLoc(), true, BSS, DS); + D.getBSCScopeSpec() = BSS; (this->*DirectDeclParser)(D); return; } @@ -6554,8 +6556,9 @@ void Parser::ParseFunctionDeclarator(Declarator &D, } else { if (Tok.isNot(tok::r_paren)) { const Type *typePtr = nullptr; - if (!D.getExtendedType().isNull()) { - typePtr = D.getExtendedType().getTypePtrOrNull(); + if (D.getBSCScopeSpec().isNotEmpty() && + !D.getBSCScopeSpec().getExtendedType().isNull()) { + typePtr = D.getBSCScopeSpec().getExtendedType().getTypePtrOrNull(); if (typePtr) typePtr = typePtr->getCanonicalTypeUnqualified().getTypePtrOrNull(); } @@ -6567,8 +6570,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D, if (ParamInfo.size() > 0) { ParmVarDecl *PD = dyn_cast_or_null(ParamInfo.data()[0].Param); - if (PD && !D.getExtendedType().isNull()) - D.HasThisParam = PD->IsThisParam; + if (PD && !D.getBSCScopeSpec().getExtendedType().isNull()) + D.getBSCScopeSpec().HasThisParam = PD->IsThisParam; } HasProto = ParamInfo.size() || getLangOpts().CPlusPlus || getLangOpts().OpenCL; diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 9cdd191aec4fd9fb8b5999ca51e72f5bae064353..9225ef74a91f8531771d3be25f480b6b141d1556 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -733,20 +733,24 @@ ExprResult Parser::ParseOptionalBSCScopeSpecifier( CastParseKind ParseKind, bool isAddressOfOperand, bool &NotCastExpr, TypeCastState isTypeCast, bool isVectorLiteral, bool *NotPrimaryExpression, bool HasBSCScopeSpec) { - ParsingDeclSpec BSS(*this); - ParseBSCScopeSpecifiers(BSS); - ParsingDeclarator D(*this, BSS, DeclaratorContext::File); - D.setBSCScopeSpec(&BSS); - QualType T = Actions.ConvertBSCScopeSpecToType( - D, BSS.getBeginLoc(), false); // get scope type for BSC + ParsingDeclSpec DS(*this); + ParseBSCScopeSpecifiers(DS); + ParsingDeclarator D(*this, DS, DeclaratorContext::File); + + BSCScopeSpec BSS; + BSS.setBeginLoc(DS.getBeginLoc()); + QualType T = + Actions.ConvertBSCScopeSpecToType(D, DS.getBeginLoc(), false, BSS, DS); HasBSCScopeSpec = TryConsumeToken(tok::coloncolon); + D.getBSCScopeSpec() = BSS; + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_unqualified_id) << 0; return ExprError(); } return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, isTypeCast, isVectorLiteral, NotPrimaryExpression, - T, HasBSCScopeSpec); + T, HasBSCScopeSpec, DS.getBeginLoc()); } /// Parse a cast-expression, or, if \pisUnaryExpression is true, parse @@ -929,11 +933,10 @@ ExprResult Parser::ParseOptionalBSCScopeSpecifier( /// '__is_rvalue_expr' /// \endverbatim /// -ExprResult -Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, - bool &NotCastExpr, TypeCastState isTypeCast, - bool isVectorLiteral, bool *NotPrimaryExpression, - QualType T, bool HasBSCScopeSpec) { +ExprResult Parser::ParseCastExpression( + CastParseKind ParseKind, bool isAddressOfOperand, bool &NotCastExpr, + TypeCastState isTypeCast, bool isVectorLiteral, bool *NotPrimaryExpression, + QualType T, bool HasBSCScopeSpec, SourceLocation BL) { ExprResult Res; tok::TokenKind SavedKind = Tok.getKind(); auto SavedType = PreferredType; @@ -1846,8 +1849,12 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, // These can be followed by postfix-expr pieces. PreferredType = SavedType; - if (Res.get()) - Res.get()->HasBSCScopeSpec = HasBSCScopeSpec; + if (Res.get()) { + if (HasBSCScopeSpec && BL.isValid()) { + Res.get()->HasBSCScopeSpec = HasBSCScopeSpec; + Res.get()->setExtendedTypeBeginLoc(BL); + } + } Res = ParsePostfixExpressionSuffix(Res); if (getLangOpts().OpenCL) if (Expr *PostfixExpr = Res.get()) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index fd712ce8fc5b5f3666fb1759a09af424cf7d15fc..76b1cfbd2a0075201a2ea4e4fdf4f06cc5768a7d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5768,9 +5768,12 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, if (RebuildDeclaratorInCurrentInstantiation(*this, D, Name)) D.setInvalidType(); } - } else if (!D.getExtendedType().isNull()) { - DC = getASTContext().BSCDeclContextMap - [D.getExtendedType().getCanonicalType().getTypePtr()]; + } else if (D.getBSCScopeSpec().isNotEmpty() && + !D.getBSCScopeSpec().getExtendedType().isNull()) { + DC = getASTContext().BSCDeclContextMap[D.getBSCScopeSpec() + .getExtendedType() + .getCanonicalType() + .getTypePtr()]; } TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); @@ -5813,7 +5816,8 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, } LookupName(Previous, S, CreateBuiltins); - if (!D.getExtendedType().isNull()) { // BSCMethod only + if (D.getBSCScopeSpec().isNotEmpty() && + !D.getBSCScopeSpec().getExtendedType().isNull()) { // BSCMethod only LookupQualifiedName(Previous, DC); // Lookup for struct / union members. } } else { // Something like "int foo::x;" @@ -8451,7 +8455,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // - the type R of the function is some kind of typedef or other non- // attributed reference to a type name (which eventually refers to a // function type). - if (SemaRef.getLangOpts().BSC && D.getBSCScopeSpec() != nullptr) { + if (SemaRef.getLangOpts().BSC && D.getBSCScopeSpec().isNotEmpty()) { ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier(); if (ConstexprKind == ConstexprSpecKind::Constinit) { SemaRef.Diag(D.getDeclSpec().getConstexprSpecLoc(), @@ -8466,8 +8470,9 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, BSCMethodDecl *Ret = BSCMethodDecl::Create( SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC, isInline, ConstexprKind, SourceLocation(), TrailingRequiresClause); - Ret->setHasThisParam(D.HasThisParam); - Ret->setExtendedType(D.getExtendedType()); + Ret->setHasThisParam(D.getBSCScopeSpec().HasThisParam); + Ret->setExtendedType(D.getBSCScopeSpec().getExtendedType()); + Ret->setExtentedTypeBeginLoc(D.getBSCScopeSpec().getBeginLoc()); return Ret; } bool HasPrototype = diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 75e8e350bd48dd209b201e03006ed34163325fb7..482259712998a22ec85519e96ebc27586c274e79 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1283,14 +1283,13 @@ static QualType ConvertConstrainedAutoDeclSpecToType(Sema &S, DeclSpec &DS, /// \returns The type described by the declaration specifiers. This function /// never returns null. static QualType ConvertDeclSpecToType(TypeProcessingState &state, - bool BSCMethodFlag = false) { + DeclSpec &PDS) { // FIXME: Should move the logic from DeclSpec::Finish to here for validity // checking. Sema &S = state.getSema(); Declarator &declarator = state.getDeclarator(); - DeclSpec &DS = BSCMethodFlag ? *(declarator.getBSCScopeSpec()) - : declarator.getMutableDeclSpec(); + DeclSpec &DS = PDS; SourceLocation DeclLoc = declarator.getIdentifierLoc(); if (DeclLoc.isInvalid()) DeclLoc = DS.getBeginLoc(); @@ -1838,16 +1837,16 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state, } QualType Sema::ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc, - bool AddToContextMap) { + bool AddToContextMap, + BSCScopeSpec &BSS, DeclSpec &DS) { TypeProcessingState state(*this, D); - bool BSCMethodFlag = true; - QualType T = ConvertDeclSpecToType(state, BSCMethodFlag); + QualType T = ConvertDeclSpecToType(state, DS); NamedDecl *Def = nullptr; if (T->isIncompleteType(&Def)) { BoundTypeDiagnoser<> Diagnoser(diag::err_typecheck_decl_incomplete_type); Diagnoser.diagnose(*this, Loc, T); } else if (AddToContextMap) { - D.setExtendedType(T); + BSS.setExtendedType(T); const Type *BasedType = T.getCanonicalType().getTypePtr(); // build declcontext map if (getASTContext().BSCDeclContextMap.find(BasedType) == @@ -3304,7 +3303,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case UnqualifiedIdKind::IK_Identifier: case UnqualifiedIdKind::IK_LiteralOperatorId: case UnqualifiedIdKind::IK_TemplateId: - T = ConvertDeclSpecToType(state); + T = ConvertDeclSpecToType(state, D.getMutableDeclSpec()); if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) { OwnedTagDecl = cast(D.getDeclSpec().getRepAsDecl()); diff --git a/clang/test/BSC/Method/test.cbs b/clang/test/BSC/Driver/rewrite-bsc/rewrite_bsc_header.hbs similarity index 33% rename from clang/test/BSC/Method/test.cbs rename to clang/test/BSC/Driver/rewrite-bsc/rewrite_bsc_header.hbs index 310f3121270eaadd1957fd9a85359cdbad2772d4..d84c3654a44e11f37139f617d28916b11c9ef505 100644 --- a/clang/test/BSC/Method/test.cbs +++ b/clang/test/BSC/Driver/rewrite-bsc/rewrite_bsc_header.hbs @@ -1,7 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics +#ifndef REWRITE_H +#define REWRITE_H -/* Wait to be opened after BSC-member-function feature is implemented. struct Foo { int a; }; @@ -14,14 +13,4 @@ void int::increase(int *this) { *this = *this + 1; } -*/ - -int main() { - /* - struct Foo foo = {.a = 42}; - int a = foo.getA(); // a is 42 - int b = 41; - b.increase(); // b is 42 - */ - return 0; -} \ No newline at end of file +#endif diff --git a/clang/test/BSC/Driver/rewrite-bsc/rewrite_bsc_option.cbs b/clang/test/BSC/Driver/rewrite-bsc/rewrite_bsc_option.cbs new file mode 100644 index 0000000000000000000000000000000000000000..0b90b7fd652331b1128b3caf58c7eef8f9c187b4 --- /dev/null +++ b/clang/test/BSC/Driver/rewrite-bsc/rewrite_bsc_option.cbs @@ -0,0 +1,48 @@ +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this) { + return this->a; +} + +void int::increase(int *this) { + *this = *this + 1; +} + + + +int main() { + struct Foo foo = {.a = 42}; + int a = foo.getA(); // a is 42 + int b = 41; + b.increase(); // b is 42 + int::increase(&b); + return 0; +} + +// CHECK:struct Foo { +// CHECK-NEXT: int a; +// CHECK-NEXT:}; + +// CHECK:int struct_Foo_getA(struct Foo* this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT:} + +// CHECK:void int_increase(int *this) { +// CHECK-NEXT: *this = *this + 1; +// CHECK-NEXT:} + +// CHECK:int main() { +// CHECK-NEXT: struct Foo foo = {.a = 42}; +// CHECK-NEXT: int a = struct_Foo_getA(&foo); +// CHECK-NEXT: int b = 41; +// CHECK-NEXT: int_increase(&b); +// CHECK-NEXT: int_increase(&b); +// CHECK-NEXT: return 0; +// CHECK-NEXT:} diff --git a/clang/test/BSC/Driver/rewrite-bsc/rewrite_bsc_option_ignore.c b/clang/test/BSC/Driver/rewrite-bsc/rewrite_bsc_option_ignore.c new file mode 100644 index 0000000000000000000000000000000000000000..b9814bbf03d31ff203641576f6a3a4fc1f59166b --- /dev/null +++ b/clang/test/BSC/Driver/rewrite-bsc/rewrite_bsc_option_ignore.c @@ -0,0 +1,4 @@ +// RUN: %clang -rewrite-bsc %s +// WARN: warning: ignoring '-rewrite-bsc' option because rewriting input type 'c' is not supported [-Woption-ignored] + +int main() { return 0; } \ No newline at end of file diff --git a/clang/test/BSC/Driver/rewrite-bsc/rewrite_bsc_with_header.cbs b/clang/test/BSC/Driver/rewrite-bsc/rewrite_bsc_with_header.cbs new file mode 100644 index 0000000000000000000000000000000000000000..8fe7ebcd0b5ec668e767dd84b2e61583860d4a1c --- /dev/null +++ b/clang/test/BSC/Driver/rewrite-bsc/rewrite_bsc_with_header.cbs @@ -0,0 +1,36 @@ +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output + +#include "rewrite_bsc_header.hbs" + +int main() { + struct Foo foo = {.a = 42}; + int a = foo.getA(); // a is 42 + int b = 41; + b.increase(); // b is 42 + int::increase(&b); + return 0; +} + +// CHECK: struct Foo { +// CHECK-NEXT: int a; +// CHECK-NEXT: }; + +// CHECK: int struct_Foo_getA(struct Foo* this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: void int_increase(int *this) { +// CHECK-NEXT: *this = *this + 1; +// CHECK-NEXT: } + +// CHECK: int main() { +// CHECK-NEXT: struct Foo foo = {.a = 42}; +// CHECK-NEXT: int a = struct_Foo_getA(&foo); +// CHECK-NEXT: int b = 41; +// CHECK-NEXT: int_increase(&b); +// CHECK-NEXT: int_increase(&b); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Driver/std_option.cbs b/clang/test/BSC/Driver/std-option/std_option.cbs similarity index 100% rename from clang/test/BSC/Driver/std_option.cbs rename to clang/test/BSC/Driver/std-option/std_option.cbs diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function.cbs index 313e67cb94c7b94a00fc041ce1e0a19bd1c5a000..7c9ebf78b50cc520bffc1e3f25a49f4a5cf5ce2c 100644 --- a/clang/test/BSC/Method/BuiltInType/int_instance_function.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics void int::increase(int* this) { @@ -9,4 +13,14 @@ int main() { int x = 1; x.increase(); return 0; -} \ No newline at end of file +} + +// CHECK: void int_increase(int* this) { +// CHECK-NEXT: *this = *this +1; +// CHECK-NEXT: } + +// CHECK: int main() { +// CHECK-NEXT: int x = 1; +// CHECK-NEXT: int_increase(&x); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_arrow.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_arrow.cbs index 6ea672dbc77f2d4f26690d4896b8df33c277b255..1c43f7a93d58b9ba6f49e0bdbac4d3b1b6b61d54 100644 --- a/clang/test/BSC/Method/BuiltInType/int_instance_function_arrow.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_arrow.cbs @@ -1,5 +1,9 @@ // RUN: %clang %s -o %t.output // RUN: %t.output +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics #include @@ -18,3 +22,18 @@ int main() { printf("%d", x); return *y - 3; } + +// CHECK: void int_increase(int* this) { +// CHECK-NEXT: *this = *this +1; +// CHECK-NEXT: } + + +// CHECK:int main() { +// CHECK-NEXT: int x = 1; +// CHECK-NEXT: int* y = &x; +// CHECK-NEXT: int_increase(y); +// CHECK-NEXT: int_increase(y); +// CHECK-NEXT: printf("%d", *y); +// CHECK-NEXT: printf("%d", x); +// CHECK-NEXT: return *y - 3; +// CHECK-NEXT: } diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_arrow_const_param.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_arrow_const_param.cbs index 8b365bd4588f9dce42c7a44ae566414eb6de8943..d8a0a5c9a00406848b5c84543edea205d931d596 100644 --- a/clang/test/BSC/Method/BuiltInType/int_instance_function_arrow_const_param.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_arrow_const_param.cbs @@ -1,5 +1,9 @@ // RUN: %clang %s -o %t.output // RUN: %t.output +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics #include @@ -18,3 +22,18 @@ int main() { printf("%d", x); return *y - 1; } + +// CHECK: void int_increase(const int* this) { +// CHECK-NEXT: return; +// CHECK-NEXT:} + + +// CHECK: int main() { +// CHECK-NEXT: int x = 1; +// CHECK-NEXT: int* y = &x; +// CHECK-NEXT: int_increase(y); +// CHECK-NEXT: int_increase(y); +// CHECK-NEXT: printf("%d", *y); +// CHECK-NEXT: printf("%d", x); +// CHECK-NEXT: return *y - 1; +// CHECK-NEXT:} diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_arrow_vloatile_param.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_arrow_vloatile_param.cbs index 5066755a8cc0b71986d6631940c4e1faf59b257f..46c0d26fce806e92a65f9e710afe8f6580ed5960 100644 --- a/clang/test/BSC/Method/BuiltInType/int_instance_function_arrow_vloatile_param.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_arrow_vloatile_param.cbs @@ -1,5 +1,9 @@ // RUN: %clang %s -o %t.output // RUN: %t.output +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics #include @@ -18,3 +22,19 @@ int main() { printf("%d", x); return *y - 1; } + + +// CHECK: void int_increase(volatile int* this) { +// CHECK-NEXT: return; +// CHECK-NEXT: } + + +// CHECK: int main() { +// CHECK-NEXT: int x = 1; +// CHECK-NEXT: int* y = &x; +// CHECK-NEXT: int_increase(y); +// CHECK-NEXT: int_increase(y); +// CHECK-NEXT: printf("%d", *y); +// CHECK-NEXT: printf("%d", x); +// CHECK-NEXT: return *y - 1; +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs index 5869645b7c24023b6ef9bb6b30a0363aeb30ca6a..ab5d07f8abf8b71ecde434714dd791bec15c37be 100644 --- a/clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics void int::increase(int* this) { @@ -12,4 +16,17 @@ int main() { fp1(&foo); fp2(&foo); return 0; -} \ No newline at end of file +} + +// CHECK: void int_increase(int* this) { +// CHECK-NEXT: *this = *this +1; +// CHECK-NEXT: } + +// CHECK: int main() { +// CHECK-NEXT: int foo = 1; +// CHECK-NEXT: void (*fp1)(int *) = int_increase; +// CHECK-NEXT: void (*fp2)(int *) = &int_increase; +// CHECK-NEXT: fp1(&foo); +// CHECK-NEXT: fp2(&foo); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs index 6b5890a2b44247855731d80b59d52dd5630bedb5..36d010ec89d64d0684d0e01206c6b3d8fbc1fb14 100644 --- a/clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs @@ -1,4 +1,7 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang_cc1 %t-rw.c -o %t-rw.output // expected-no-diagnostics typedef int bscInt; @@ -13,4 +16,18 @@ void int::increase_2(bscInt* this) { void int::increase_3(int* this) { *this = *this + 1; -} \ No newline at end of file +} + +// CHECK: typedef int bscInt; + +// CHECK: void bscInt_increase_1(bscInt* this) { +// CHECK-NEXT: *this = *this + 1; +// CHECK-NEXT: } + +// CHECK: void int_increase_2(bscInt* this) { +// CHECK-NEXT: *this = *this + 1; +// CHECK-NEXT: } + +// CHECK: void int_increase_3(int* this) { +// CHECK-NEXT: *this = *this + 1; +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_static_function_call.cbs b/clang/test/BSC/Method/BuiltInType/int_static_function_call.cbs index 9c747a9ed7713c88ffca994fae4b3132ac7e9c84..5bc1eb828cd9571c8c8b7fb7b8f7d0a83060b9a1 100644 --- a/clang/test/BSC/Method/BuiltInType/int_static_function_call.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_static_function_call.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics int int::getA() { @@ -9,4 +13,14 @@ int main() { int::getA(); int a = int::getA(); return a - 2; -} \ No newline at end of file +} + +//CHECK: int int_getA() { +//CHECK-NEXT: return 2; +//CHECK-NEXT: } + +//CHECK: int main() { +//CHECK-NEXT: int_getA(); +//CHECK-NEXT: int a = int_getA(); +//CHECK-NEXT: return a - 2; +//CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function.cbs b/clang/test/BSC/Method/Enum/enum_instance_function.cbs index c1a3b7be71196b15c84bc181c684d41bd4189a82..34253a76f3b4ba8a43e087997df4b4bba97f3960 100644 --- a/clang/test/BSC/Method/Enum/enum_instance_function.cbs +++ b/clang/test/BSC/Method/Enum/enum_instance_function.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics enum E { @@ -14,4 +18,14 @@ int main() { enum E foo = X3; foo.getA(); return 0; -} \ No newline at end of file +} + +// CHECK: int enum_E_getA(enum E* this) { +// CHECK-NEXT: return X4; +// CHECK-NEXT: } + +// CHECK: int main() { +// CHECK: enum E foo = X3; +// CHECK-NEXT: enum_E_getA(&foo); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_2.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_2.cbs index 1c59e2595892afe3b25e0d51de7eac227bff4148..6a9513272a9ede2acebb71984a9625df4faeed19 100644 --- a/clang/test/BSC/Method/Enum/enum_instance_function_2.cbs +++ b/clang/test/BSC/Method/Enum/enum_instance_function_2.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics enum E { @@ -14,3 +18,17 @@ int main() { int x = foo.to_int(); return 0; } + +// CHECK: enum E { +// CHECK-NEXT: X3 +// CHECK-NEXT: }; + +// CHECK: int enum_E_to_int(enum E* this) { +// CHECK-NEXT: return (int)*this; +// CHECK-NEXT: } + +// CHECK: int main() { +// CHECK-NEXT: enum E foo = X3; +// CHECK-NEXT: int x = enum_E_to_int(&foo); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_3.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_3.cbs index 2cc575e7138c0d47431d4e2ed109dfbc03708f5c..c0a42df43b69b1ddc64750444728f91ab17ca111 100644 --- a/clang/test/BSC/Method/Enum/enum_instance_function_3.cbs +++ b/clang/test/BSC/Method/Enum/enum_instance_function_3.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics enum E { @@ -14,3 +18,17 @@ int main() { int x = foo.to_int(1); return 0; } + +// CHECK: enum E { +// CHECK-NEXT: X3 +// CHECK-NEXT: }; + +// CHECK: int enum_E_to_int(enum E* this, int a) { +// CHECK-NEXT: return a; +// CHECK-NEXT: } + +// CHECK: int main() { +// CHECK-NEXT: enum E foo = X3; +// CHECK-NEXT: int x = enum_E_to_int(&foo, 1); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_arrow.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_arrow.cbs index 4d3dae73068751ae356619416d6a02f06d1a83d9..00edcfb653e89b620454f41b81e88c1ecfa2ef11 100644 --- a/clang/test/BSC/Method/Enum/enum_instance_function_arrow.cbs +++ b/clang/test/BSC/Method/Enum/enum_instance_function_arrow.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics enum E { @@ -16,3 +20,17 @@ int main() { return 0; } +// CHECK: enum E { +// CHECK-NEXT: X3 +// CHECK-NEXT: }; + +// CHECK: int enum_E_to_int(enum E* this) { +// CHECK-NEXT: return (int)*this; +// CHECK-NEXT: } + +// CHECK: int main() { +// CHECK-NEXT: enum E foo = X3; +// CHECK-NEXT: enum E* f = &foo; +// CHECK-NEXT: int x = enum_E_to_int(f); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_declaration_only.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_declaration_only.cbs index 033b968b111040d8e11fbdd159aa839376af64c8..3b2b00729951e5d94c1c03e9d3269973468481ee 100644 --- a/clang/test/BSC/Method/Enum/enum_instance_function_declaration_only.cbs +++ b/clang/test/BSC/Method/Enum/enum_instance_function_declaration_only.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics enum E { @@ -13,3 +17,14 @@ int main() { return 0; } +// CHECK: enum E { +// CHECK-NEXT: X3, +// CHECK-NEXT: X4 +// CHECK-NEXT: }; + +// CHECK: int enum_E_getA(enum E* this); + +// CHECK: int main() { +// CHECK-NEXT: enum E foo = X3; +// CHECK-NEXT: return 0; +// CHECK-NEXT: } diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs index 2681e682d0d6b223695d8169027b8cee02eb9914..88e4b6caba40e9e18af97d571387919eed6aa845 100644 --- a/clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs +++ b/clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics enum E { @@ -17,4 +21,22 @@ int main() { fp1(&foo); fp2(&foo); return 0; -} \ No newline at end of file +} + +// CHECK: enum E { +// CHECK-NEXT: X3, +// CHECK-NEXT: X4 +// CHECK-NEXT: }; + +// CHECK: int enum_E_getA(enum E* this) { +// CHECK-NEXT: return X4; +// CHECK-NEXT: } + +// CHECK: int main() { +// CHECK-NEXT: enum E foo = X3; +// CHECK-NEXT: int (*fp1)(enum E *) = enum_E_getA; +// CHECK-NEXT: int (*fp2)(enum E *) = &enum_E_getA; +// CHECK-NEXT: fp1(&foo); +// CHECK-NEXT: fp2(&foo); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_same_name.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_same_name.cbs index 27daadfbd559fcf5d5e4e83d3a6ea0dea4a7eda0..79073a4ff5e1de960676c520665f54b8dadf72bd 100644 --- a/clang/test/BSC/Method/Enum/enum_instance_function_same_name.cbs +++ b/clang/test/BSC/Method/Enum/enum_instance_function_same_name.cbs @@ -1,5 +1,9 @@ // RUN: %clang %s -o %t.output // RUN: %t.output +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics @@ -22,4 +26,25 @@ int main() { enum E foo = X3; foo.getA(); return foo.getA() + a.getA() - 1; -} \ No newline at end of file +} + +// CHECK: enum E { +// CHECK-NEXT: X3, +// CHECK-NEXT: X4 +// CHECK-NEXT: }; + +// CHECK: int enum_E_getA(enum E* this) { +// CHECK-NEXT: return X3; +// CHECK-NEXT: } + +// CHECK: int int_getA(int* this) { +// CHECK-NEXT: return X4; +// CHECK-NEXT: } + +// CHECK: int main() { +// CHECK-NEXT: int a = 1; +// CHECK-NEXT: int_getA(&a); +// CHECK-NEXT: enum E foo = X3; +// CHECK-NEXT: enum_E_getA(&foo); +// CHECK-NEXT: return enum_E_getA(&foo) + int_getA(&a) - 1; +// CHECK-NEXT: } diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_typedef.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_typedef.cbs index 5a1aebbb796815996adcf599e4faa77285200d2d..ae051b4d4cbd6dca1a5c8558c10561d40a3e2568 100644 --- a/clang/test/BSC/Method/Enum/enum_instance_function_typedef.cbs +++ b/clang/test/BSC/Method/Enum/enum_instance_function_typedef.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics enum E { @@ -30,4 +34,35 @@ int main() { f.getA(); f.getC(); return 0; -} \ No newline at end of file +} + +// CHECK: enum E { +// CHECK-NEXT: X3, +// CHECK-NEXT: X4 +// CHECK-NEXT: }; + +// CHECK: typedef enum E F; +// CHECK-NEXT: int F_getA(enum E* this) { +// CHECK-NEXT: return X4; +// CHECK-NEXT: } + +// CHECK: int F_getB(F* this) { +// CHECK-NEXT: return X4; +// CHECK-NEXT: } + +// CHECK: int enum_E_getC(F* this) { +// CHECK-NEXT: return X4; +// CHECK-NEXT: } + +// CHECK: int main() { +// CHECK-NEXT: enum E foo = X3; +// CHECK-NEXT: F_getA(&foo); +// CHECK-NEXT: F_getB(&foo); +// CHECK-NEXT: enum_E_getC(&foo); + +// CHECK: F f = foo; +// CHECK-NEXT: F_getB(&f); +// CHECK-NEXT: F_getA(&f); +// CHECK-NEXT: enum_E_getC(&f); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs index 2042dba0cef01f14ac1dae783ecdb66d74e588d4..c917fa2f90f709a73d0c348de139ec5edd888fc6 100644 --- a/clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs +++ b/clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs @@ -1,4 +1,7 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang_cc1 %t-rw.c -o %t-rw.output // expected-no-diagnostics typedef enum E { @@ -16,4 +19,21 @@ int E::getX4_2(enum E* this) { int enum E::getX4_3(enum E* this) { return X4; -} \ No newline at end of file +} + +// CHECK: typedef enum E { +// CHECK-NEXT: X3, +// CHECK-NEXT: X4 +// CHECK-NEXT: }E; + +// CHECK: int E_getX4_1(E* this) { +// CHECK-NEXT: return X4; +// CHECK-NEXT: } + +// CHECK: int E_getX4_2(enum E* this) { +// CHECK-NEXT: return X4; +// CHECK-NEXT: } + +// CHECK: int enum_E_getX4_3(enum E* this) { +// CHECK-NEXT: return X4; +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_normal_top_level.cbs b/clang/test/BSC/Method/Enum/enum_normal_top_level.cbs index 32abe22b40f2d1aa919dc23ac7e949446bbfdd6f..82833030555f041f3ec6f9e829fc83460528307a 100644 --- a/clang/test/BSC/Method/Enum/enum_normal_top_level.cbs +++ b/clang/test/BSC/Method/Enum/enum_normal_top_level.cbs @@ -1,4 +1,7 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang_cc1 %t-rw.c -o %t-rw.output // expected-no-diagnostics enum E { @@ -8,3 +11,5 @@ enum E { int getA(enum E this); + +// CHECK: int getA(enum E this); diff --git a/clang/test/BSC/Method/Struct/struct_instance_function.cbs b/clang/test/BSC/Method/Struct/struct_instance_function.cbs index 416f7e75c499a23c77a7182c2a9cc0f97ce073f0..5cf498dc354146983b727ea086287aaa3ac5aa0f 100644 --- a/clang/test/BSC/Method/Struct/struct_instance_function.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_function.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics struct Foo { @@ -14,4 +18,19 @@ int main() { struct Foo foo = {.a = 1}; foo.getA(); return 0; -} \ No newline at end of file +} + +// CHECK: struct Foo { +// CHECK-NEXT: int a; +// CHECK-NEXT: }; + +// CHECK: int struct_Foo_getA(struct Foo* this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + + +// CHECK: int main() { +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: struct_Foo_getA(&foo); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_chaining.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_chaining.cbs index 7ed034adbb38f2e858520cefffaffc5cecb44b1b..c0da01a73f42b46e9cb439a4b916be12e8e71caa 100644 --- a/clang/test/BSC/Method/Struct/struct_instance_function_chaining.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_function_chaining.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics struct queue { @@ -20,4 +24,24 @@ int main() { struct Scheduler s; s.run(); return 0; -} \ No newline at end of file +} + +// CHECK: struct queue { +// CHECK-NEXT: }; + +// CHECK: void struct_queue_isEmpty(struct queue* this){} + +// CHECK: struct Scheduler { +// CHECK-NEXT: struct queue* que; +// CHECK: }; + +// CHECK: void struct_Scheduler_run(struct Scheduler* this) { +// CHECK-NEXT: struct_queue_isEmpty(this->que); +// CHECK-NEXT: struct_queue_isEmpty(&(*this->que)); +// CHECK-NEXT: } + +// CHECK: int main() { +// CHECK-NEXT: struct Scheduler s; +// CHECK-NEXT: struct_Scheduler_run(&s); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs index e6c4c2fcd2f365658c675c20a589a017cd20e4aa..2d743b3263b9e14113ce18242aa15ee007fd48dd 100644 --- a/clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics struct Foo { @@ -16,3 +20,19 @@ int main() { int struct Foo::getA(struct Foo* this) { return this->a; } + +// CHECK: struct Foo { +// CHECK-NEXT: int a; +// CHECK-NEXT: }; + +// CHECK: int struct_Foo_getA(struct Foo* this); + +// CHECK: int main() { +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: struct_Foo_getA(&foo); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } + +// CHECK: int struct_Foo_getA(struct Foo* this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs index ff1fdddc42e4e7d418d4c975e4a89041a66f34fa..452355f740434ac4c197bdbe3671bc3a63f2a679 100644 --- a/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics struct Foo { @@ -16,4 +20,21 @@ int main() { int struct Foo::getA(struct Foo* this) { return this->a; -} \ No newline at end of file +} + +// CHECK: struct Foo { +// CHECK-NEXT: int a; +// CHECK-NEXT: }; + +// CHECK: int struct_Foo_getA(struct Foo* this); +// CHECK-NEXT: int struct_Foo_getA(struct Foo* this); + +// CHECK: int main() { +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: struct_Foo_getA(&foo); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } + +// CHECK: int struct_Foo_getA(struct Foo* this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_parens.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_parens.cbs index 95c0519ec14be9fcb1dffa8b522c6bbb60feb666..a79d2def80bdaa7a330b1046f0df85e63631b036 100644 --- a/clang/test/BSC/Method/Struct/struct_instance_function_parens.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_function_parens.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics typedef struct _queue { @@ -12,4 +16,17 @@ void destroyQueue(queue** q) { (*q)->reverse(); (**q).reverse(); } -int main() {return 0;} \ No newline at end of file +int main() {return 0;} + +// CHECK: typedef struct _queue { +// CHECK-NEXT: }queue; + +// CHECK: queue* queue_reverse(queue* this) { +// CHECK-NEXT: return this; +// CHECK-NEXT: } + +// CHECK: void destroyQueue(queue** q) { +// CHECK-NEXT: queue_reverse((*q)); +// CHECK-NEXT: queue_reverse(&(**q)); +// CHECK-NEXT: } +// CHECK-NEXT: int main() {return 0;} diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs index ebd1a859d149a3ea21c60898f4ae3d8abcaacdb2..5ac275fcc4f1744ed181d6a5feb57cd45a22b945 100644 --- a/clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics struct Foo { @@ -17,4 +21,18 @@ int main() { fp1(&foo); fp2(&foo); return 0; -} \ No newline at end of file +} + +// CHECK: int struct_Foo_getA(struct Foo* this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + + +// CHECK: int main() { +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: int (*fp1)(struct Foo *) = struct_Foo_getA; +// CHECK-NEXT: int (*fp2)(struct Foo *) = &struct_Foo_getA; +// CHECK-NEXT: fp1(&foo); +// CHECK-NEXT: fp2(&foo); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_with_typedef.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_with_typedef.cbs index a48f320d52ff73f67dd1878c16a2fa7b3642fd7c..c12ed6e0ec2f4dd1f73b9bdd6ff3afd18ed25cf7 100644 --- a/clang/test/BSC/Method/Struct/struct_instance_function_with_typedef.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_function_with_typedef.cbs @@ -1,4 +1,7 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang_cc1 %t-rw.c -o %t-rw.output // expected-no-diagnostics typedef struct Foo { @@ -16,4 +19,16 @@ int Foo::getAPlusB(struct Foo* this) { int struct Foo::getA(struct Foo* this) { return this->a; -} \ No newline at end of file +} + +// CHECK: int Foo_getB(Foo* this) { +// CHECK-NEXT: return this->b; +// CHECK-NEXT: } + +// CHECK: int Foo_getAPlusB(struct Foo* this) { +// CHECK-NEXT: return this->a + this->b; +// CHECK-NEXT: } + +// CHECK: int struct_Foo_getA(struct Foo* this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } diff --git a/clang/test/BSC/Method/Struct/struct_instance_recursive_call.cbs b/clang/test/BSC/Method/Struct/struct_instance_recursive_call.cbs index 612dff1da1a57fbb6963cf6d577dd7fcc09216e3..946bb824ea6a4974f21b79e956c843dd75a16b11 100644 --- a/clang/test/BSC/Method/Struct/struct_instance_recursive_call.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_recursive_call.cbs @@ -1,4 +1,7 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang_cc1 %t-rw.c -o %t-rw.output // expected-no-diagnostics typedef struct _queue { @@ -7,4 +10,12 @@ typedef struct _queue { queue* queue::reverse(queue* this) { this->reverse(); return this; -} \ No newline at end of file +} + +// CHECK: typedef struct _queue { +// CHECK-NEXT: }queue; + +// CHECK: queue* queue_reverse(queue* this) { +// CHECK-NEXT: queue_reverse(this); +// CHECK-NEXT: return this; +// CHECK-NEXT: } diff --git a/clang/test/BSC/Method/Struct/struct_static_function_call.cbs b/clang/test/BSC/Method/Struct/struct_static_function_call.cbs index 995c843391ff8fb32cdb55eb3cfacc7438e52b0d..f240296ff205404f0164bf4bbe4e128e81e9545c 100644 --- a/clang/test/BSC/Method/Struct/struct_static_function_call.cbs +++ b/clang/test/BSC/Method/Struct/struct_static_function_call.cbs @@ -1,5 +1,9 @@ // RUN: %clang %s -o %t.output // RUN: %t.output +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics struct Foo { @@ -16,4 +20,8 @@ int main() { struct Foo::getA(); int a = struct Foo::getA(); return a - 1; -} \ No newline at end of file +} + +// CHECK: int struct_Foo_getA() { +// CHECK: struct_Foo_getA(); +// CHECK-NEXT: int a = struct_Foo_getA(); \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_toplevel_func.cbs b/clang/test/BSC/Method/Struct/struct_toplevel_func.cbs index 268989fa775b8fcc24f5c7388ed731b96f9a9f9f..6ed620a857c96eb099de947c3c9192d674463b22 100644 --- a/clang/test/BSC/Method/Struct/struct_toplevel_func.cbs +++ b/clang/test/BSC/Method/Struct/struct_toplevel_func.cbs @@ -1,5 +1,9 @@ // RUN: %clang %s -o %t.output // RUN: %t.output +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics struct F { @@ -15,4 +19,7 @@ int increase() { int main() { return increase(); -} \ No newline at end of file +} + +// CHECK: int struct_F_increase() { + \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_instance_function_declaration.cbs b/clang/test/BSC/Method/Union/union_instance_function_declaration.cbs index e95725f032126339a9cf5452629b2050dfb64f02..ad55c19810b9ad0a37d6cf5dcb3af2ea32b2ee5c 100644 --- a/clang/test/BSC/Method/Union/union_instance_function_declaration.cbs +++ b/clang/test/BSC/Method/Union/union_instance_function_declaration.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics union SimpleUnion { @@ -17,4 +21,8 @@ int main() { int union SimpleUnion::getA(union SimpleUnion * this) { return this->ui; -} \ No newline at end of file +} + +// CHECK: int union_SimpleUnion_getA(union SimpleUnion* this); +// CHECK: union_SimpleUnion_getA(&u); +// CHECK: int union_SimpleUnion_getA(union SimpleUnion * this) { diff --git a/clang/test/BSC/Method/Union/union_instance_function_multi_declaration.cbs b/clang/test/BSC/Method/Union/union_instance_function_multi_declaration.cbs index 263d212404341cdc9f6dbbad46dab5a50e2120a2..2ec56274507583a4ab02c1760e1d19f8d1495dfb 100644 --- a/clang/test/BSC/Method/Union/union_instance_function_multi_declaration.cbs +++ b/clang/test/BSC/Method/Union/union_instance_function_multi_declaration.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics union SimpleUnion { @@ -18,4 +22,17 @@ int main() { int union SimpleUnion::getA(union SimpleUnion * this) { return this->ui; -} \ No newline at end of file +} + +// CHECK: int union_SimpleUnion_getA(union SimpleUnion* this); +// CHECK-NEXT: int union_SimpleUnion_getA(union SimpleUnion* this); + +// CHECK: int main() { +// CHECK-NEXT: union SimpleUnion u = {.ui = 1}; +// CHECK-NEXT: union_SimpleUnion_getA(&u); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } + +// CHECK: int union_SimpleUnion_getA(union SimpleUnion * this) { +// CHECK-NEXT: return this->ui; +// CHECK-NEXT: } diff --git a/clang/test/BSC/Method/Union/union_instance_function_pointer.cbs b/clang/test/BSC/Method/Union/union_instance_function_pointer.cbs index 3dc1847eb71aaab9fea07ce3e3af72b269b09ac2..08c3bda4542979db2ad65684ef5cc8359e446a2f 100644 --- a/clang/test/BSC/Method/Union/union_instance_function_pointer.cbs +++ b/clang/test/BSC/Method/Union/union_instance_function_pointer.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics union SimpleUnion { @@ -18,4 +22,17 @@ int main() { fp1(&foo); fp2(&foo); return 0; -} \ No newline at end of file +} + +// CHECK: int union_SimpleUnion_getA(union SimpleUnion * this) { +// CHECK-NEXT: return this->ui; +// CHECK-NEXT: } + +// CHECK: int main() { +// CHECK-NEXT: union SimpleUnion foo = {.ui = 1}; +// CHECK-NEXT: int (*fp1)(union SimpleUnion *) = union_SimpleUnion_getA; +// CHECK-NEXT: int (*fp2)(union SimpleUnion *) = &union_SimpleUnion_getA; +// CHECK-NEXT: fp1(&foo); +// CHECK-NEXT: fp2(&foo); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } diff --git a/clang/test/BSC/Method/ambiguous_1.cbs b/clang/test/BSC/Method/ambiguous_1.cbs index 76aa5ce27c64bd74be347c3029c0c56fb5db68bd..c5d5e44939513ce07c1a008c4ac5c464d34a1db9 100644 --- a/clang/test/BSC/Method/ambiguous_1.cbs +++ b/clang/test/BSC/Method/ambiguous_1.cbs @@ -1,4 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang_cc1 %t-rw.c -o %t-rw.output // expected-no-diagnostics long int::getA1() { @@ -16,3 +19,15 @@ short int::getA3() { int main() { return 0; }; + +// CHECK: long int_getA1() { +// CHECK-NEXT: return 1; +// CHECK-NEXT: }; + +// CHECK: unsigned int_getA2() { +// CHECK-NEXT: return 1; +// CHECK-NEXT: }; + +// CHECK: short int_getA3() { +// CHECK-NEXT: return 1; +// CHECK-NEXT: }; diff --git a/clang/test/BSC/ParamCheck/this_param_with_const.cbs b/clang/test/BSC/ParamCheck/this_param_with_const.cbs index a6c7aa7e29f16c7f2a7f7c884960b35eb1f7b04a..e12583f8894be5916d283103c3632e4029c20028 100644 --- a/clang/test/BSC/ParamCheck/this_param_with_const.cbs +++ b/clang/test/BSC/ParamCheck/this_param_with_const.cbs @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics // struct @@ -48,3 +52,14 @@ int main() { return 0; } +// CHECK: int main() { +// CHECK-NEXT: struct Foo foo ={.a = 42}; +// CHECK-NEXT: struct_Foo_getA(&foo); +// CHECK-NEXT: enum E e= X3; +// CHECK-NEXT: enum_E_getA(&e); +// CHECK-NEXT: union SimpleUnion u = {.ui = 1}; +// CHECK-NEXT: union_SimpleUnion_getA(&u); +// CHECK-NEXT: int one = 1; +// CHECK-NEXT: int_getA(&one); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/ParamCheck/this_param_with_volatile.cbs b/clang/test/BSC/ParamCheck/this_param_with_volatile.cbs index 2402e40ffdbe5b6e7123334802554abe399a72d9..daec7366b466ee42ea9e154a83ffe21e5d2b649d 100644 --- a/clang/test/BSC/ParamCheck/this_param_with_volatile.cbs +++ b/clang/test/BSC/ParamCheck/this_param_with_volatile.cbs @@ -1,4 +1,7 @@ // RUN: %clang_cc1 -verify %s +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output // expected-no-diagnostics // struct