diff --git a/clang/include/clang/Rewrite/Frontend/ASTConsumers.h b/clang/include/clang/Rewrite/Frontend/ASTConsumers.h index fed493a4318e315ea4cb8d5c75e1eb2a3021bdbe..ba9fb782859af4266c35d38f0f8d5b8e04b3d1d7 100644 --- a/clang/include/clang/Rewrite/Frontend/ASTConsumers.h +++ b/clang/include/clang/Rewrite/Frontend/ASTConsumers.h @@ -38,11 +38,10 @@ CreateModernObjCRewriter(const std::string &InFile, #if ENABLE_BSC // 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, - bool InsertLine); +std::unique_ptr +CreateBSCRewriter(const std::string &InFile, std::unique_ptr OS, + DiagnosticsEngine &Diags, const LangOptions &LOpts, + Preprocessor &PP, bool InsertLine); #endif /// CreateHTMLPrinter - Create an AST consumer which rewrites source code to diff --git a/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/clang/lib/Frontend/Rewrite/FrontendActions.cpp index df9cd4058529bd4f5856a6cda48c304034289388..d2b7f47009c090ec4dd14d4b503c326a02ff48bd 100644 --- a/clang/lib/Frontend/Rewrite/FrontendActions.cpp +++ b/clang/lib/Frontend/Rewrite/FrontendActions.cpp @@ -185,7 +185,8 @@ RewriteBSCAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { CI.createDefaultOutputFile(false, InFile, "c")) { bool InsertLine = CI.getFrontendOpts().InsertLineDirectives; return CreateBSCRewriter(std::string(InFile), std::move(OS), - CI.getDiagnostics(), CI.getLangOpts(), InsertLine); + CI.getDiagnostics(), CI.getLangOpts(), + CI.getPreprocessor(), InsertLine); } return nullptr; } diff --git a/clang/lib/Frontend/Rewrite/RewriteBSC.cpp b/clang/lib/Frontend/Rewrite/RewriteBSC.cpp index 5397f13ed0de175e2a8331ab16b99d1745b5e7a5..d249fb388e61066fd0e22e620cdef143d6b3ca95 100644 --- a/clang/lib/Frontend/Rewrite/RewriteBSC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteBSC.cpp @@ -17,6 +17,8 @@ #include "clang/AST/BSC/WalkerBSC.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" +#include "clang/Lex/MacroInfo.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Rewrite/Core/Rewriter.h" #include "clang/Rewrite/Frontend/ASTConsumers.h" #include "llvm/ADT/SmallPtrSet.h" @@ -30,7 +32,8 @@ namespace { class RewriteBSC : public ASTConsumer { public: RewriteBSC(std::string inFile, std::unique_ptr OS, - DiagnosticsEngine &D, const LangOptions &LOpts, bool insertLine); + DiagnosticsEngine &D, const LangOptions &LOpts, Preprocessor &pp, + bool insertLine); ~RewriteBSC() override {} void Initialize(ASTContext &C) override; @@ -47,6 +50,7 @@ private: FileID MainFileID; const char *MainFileStart, *MainFileEnd; std::string InFileName; + Preprocessor &PP; std::unique_ptr OutFile; // control whether to insert bsc code line info bool WithLine; @@ -71,6 +75,7 @@ private: /// Rewrite include directive form `#include "xxx.hbs"` to `#include "xxx.h"`. void RewriteInclude(); + void RewriteMacroDefinition(); void RewriteDecls(DeclContext *DC); void InsertText(SourceLocation Loc, StringRef Str, bool InsertAfter = true) { @@ -108,9 +113,10 @@ private: } // namespace RewriteBSC::RewriteBSC(std::string inFile, std::unique_ptr OS, - DiagnosticsEngine &D, const LangOptions &LOpts, bool InsertLine) - : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)), WithLine(InsertLine), - Policy(LangOpts) { + DiagnosticsEngine &D, const LangOptions &LOpts, + Preprocessor &pp, bool InsertLine) + : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)), + PP(pp), WithLine(InsertLine), Policy(LangOpts) { RewriteFailedDiag = Diags.getCustomDiagID( DiagnosticsEngine::Warning, "rewriting sub-expression within a macro (may not be correct)"); @@ -120,8 +126,10 @@ RewriteBSC::RewriteBSC(std::string inFile, std::unique_ptr OS, std::unique_ptr clang::CreateBSCRewriter(const std::string &InFile, std::unique_ptr OS, - DiagnosticsEngine &Diags, const LangOptions &LOpts, bool InsertLine) { - return std::make_unique(InFile, std::move(OS), Diags, LOpts, InsertLine); + DiagnosticsEngine &Diags, const LangOptions &LOpts, + Preprocessor &PP, bool InsertLine) { + return std::make_unique(InFile, std::move(OS), Diags, LOpts, PP, + InsertLine); } void RewriteBSC::Initialize(ASTContext &context) { @@ -186,12 +194,48 @@ void RewriteBSC::RewriteInclude() { } } +typedef std::pair id_macro_pair; +void RewriteBSC::RewriteMacroDefinition() { + std::string SStr; + llvm::raw_string_ostream Buf(SStr); + llvm::SetVector MacrosSet; + SourceLocation SL; + + for (Preprocessor::macro_iterator I = PP.macro_begin(false), + E = PP.macro_end(false); + I != E; ++I) { + auto *MD = I->second.getLatest(); + + if (MD && MD->isDefined()) { + MacroInfo *MI = MD->getMacroInfo(); + SourceLocation MacroLoc = MI->getDefinitionLoc(); + if (SM->isWrittenInMainFile(MacroLoc) && + !MacrosSet.count(id_macro_pair(I->first, MI)) && + SM->isBeforeInTranslationUnit(BeginLocOfFirstDecl, MacroLoc) && + SM->isBeforeInTranslationUnit(MacroLoc, EndLocOfLastDecl)) { + MacrosSet.insert(id_macro_pair(I->first, MI)); + const char *startBuf = SM->getCharacterData(MI->getDefinitionLoc()); + const char *endBuf = SM->getCharacterData(MI->getDefinitionEndLoc()); + unsigned len = MI->isFunctionLike() ? 1 : MI->getDefinitionLength(*SM); + if (MD->getKind() == MacroDirective::MD_Define) + Buf << "#define "; + else if (MD->getKind() == MacroDirective::MD_Undefine) + Buf << "#undef "; + Buf << std::string(startBuf, endBuf - startBuf + len); + Buf << "\n"; + } + } + } + InsertText(BeginLocOfFirstDecl, Buf.str()); +} + void RewriteBSC::HandleTranslationUnit(ASTContext &C) { if (Diags.hasErrorOccurred()) return; RewriteInclude(); // Rewrite include directives. - + GetSourceLocationsOfFirstDeclAndLastDecl(); + RewriteMacroDefinition(); RewriteDecls(C.getTranslationUnitDecl()); // Rewrite all decls. if (const RewriteBuffer *RewriteBuf = @@ -205,7 +249,6 @@ void RewriteBSC::HandleTranslationUnit(ASTContext &C) { } void RewriteBSC::RewriteDecls(DeclContext *DC) { - GetSourceLocationsOfFirstDeclAndLastDecl(); // Step 1: Find decls without bsc features. FindDeclsWithoutBSCFeature(); // Step 2: Get rewritten string @@ -672,10 +715,18 @@ const std::string RewriteBSC::GetRewrittenString() { break; if (!SM->isWrittenInMainFile(SM->getSpellingLoc(FD->getBeginLoc())) && !SM->isWrittenInMainFile(SM->getSpellingLoc(FD->getEndLoc())) && + !HasTemplateSpec && + FD->getStorageClass() == StorageClass::SC_Extern) + break; + if (!SM->isWrittenInMainFile(SM->getExpansionLoc(FD->getBeginLoc())) && + !SM->isWrittenInMainFile(SM->getExpansionLoc(FD->getEndLoc())) && !HasTemplateSpec) break; - // not found, but double negative mean it is a BSCMethodDecl. - if (DeclsWithoutBSCFeature.find(FD) == DeclsWithoutBSCFeature.end()) { + + // If it is BscMethod or macro expansion function, output the code + // according to AST; Otherwise, simply retrieve the source code + if (DeclsWithoutBSCFeature.find(FD) == DeclsWithoutBSCFeature.end() || + FD->getBeginLoc().isMacroID()) { printBSCLineInfo(FD, Buf); FD->print(Buf, Policy); } else { diff --git a/clang/test/BSC/Positive/Driver/rewrite-bsc/Macro/rewrite_bsc_with_macro_4/rewrite_bsc_with_macro_4.cbs b/clang/test/BSC/Positive/Driver/rewrite-bsc/Macro/rewrite_bsc_with_macro_4/rewrite_bsc_with_macro_4.cbs new file mode 100644 index 0000000000000000000000000000000000000000..20c0047682d06d3b89396ac638ea96343b99071b --- /dev/null +++ b/clang/test/BSC/Positive/Driver/rewrite-bsc/Macro/rewrite_bsc_with_macro_4/rewrite_bsc_with_macro_4.cbs @@ -0,0 +1,11 @@ +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: %clang %t-rw.c -I %S -o %t-rw.output +// RUN: %t-rw.output +#include "rewrite_bsc_with_macro_4.h" + +ASE_POOL_DEF(AAA, BBB); + +int main() { + ase_mmem_close_BBB(); +} + diff --git a/clang/test/BSC/Positive/Driver/rewrite-bsc/Macro/rewrite_bsc_with_macro_4/rewrite_bsc_with_macro_4.h b/clang/test/BSC/Positive/Driver/rewrite-bsc/Macro/rewrite_bsc_with_macro_4/rewrite_bsc_with_macro_4.h new file mode 100644 index 0000000000000000000000000000000000000000..3aba9a5a2309de4a47cad3d96ab9150cf38227b0 --- /dev/null +++ b/clang/test/BSC/Positive/Driver/rewrite-bsc/Macro/rewrite_bsc_with_macro_4/rewrite_bsc_with_macro_4.h @@ -0,0 +1,5 @@ +#define ASE_POOL_DEF(var_, name_) \ + void ase_mmem_close_##name_() \ + { \ + int a = 1; \ + } \ No newline at end of file diff --git a/clang/test/BSC/Positive/Driver/rewrite-bsc/Macro/rewrite_bsc_with_macro_5/rewrite_bsc_with_macro_5.cbs b/clang/test/BSC/Positive/Driver/rewrite-bsc/Macro/rewrite_bsc_with_macro_5/rewrite_bsc_with_macro_5.cbs new file mode 100644 index 0000000000000000000000000000000000000000..71dcb9988e829c503f26cd1388d9cea1676b980a --- /dev/null +++ b/clang/test/BSC/Positive/Driver/rewrite-bsc/Macro/rewrite_bsc_with_macro_5/rewrite_bsc_with_macro_5.cbs @@ -0,0 +1,88 @@ +// 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 +#ifndef NEW_CDF_DATAFRAME_TYPE_HBS +#define NEW_CDF_DATAFRAME_TYPE_HBS + +int a = 1; + +#define MINUS - +#define ONE 1 +#define HALF 0.5 +#define NEGIVE -100 +#define SQUARE(x) ((x) * (x)) + +#define ASE_POOL_DEF(var_, name_) \ + void ase_mmem_close_##name_() \ + { \ + int a = 2; \ + } \ + + +ASE_POOL_DEF(AAA, BBB); + +int int::foo(int* this) { + int b = ONE; + int result = ONE * SQUARE(2.5); + ase_mmem_close_BBB(); + return 0; +} + +int b = SQUARE(HALF); +int c = ONE NEGIVE; +int d = ONE MINUS ONE; + + +int main() { + a = ONE; + int b = SQUARE(b.foo()); + int e = (ONE * SQUARE(2.5) + b.foo()) * 2; + return 0; +} + +#endif //NEW_CDF_DATAFRAME_TYPE_HBS + + +// CHECK: #ifndef NEW_CDF_DATAFRAME_TYPE_HBS +// CHECK-NEXT: #define NEW_CDF_DATAFRAME_TYPE_HBS + +// CHECK: #define MINUS - +// CHECK: #define ONE 1 +// CHECK: #define HALF 0.5 +// CHECK: #define NEGIVE -100 + +// CHECK: #define SQUARE(x) ((x) * (x)) +// CHECK-NEXT: #define ASE_POOL_DEF(var_, name_) \ +// CHECK-NEXT: void ase_mmem_close_##name_() \ +// CHECK-NEXT: { \ +// CHECK-NEXT: int a = 2; \ +// CHECK-NEXT: } + +// CHECK: int a = 1; + +// CHECK: void ase_mmem_close_BBB(void) { +// CHECK-NEXT: int a = 2; +// CHECK-NEXT: } + +// CHECK: int int_foo(int *this) { +// CHECK-NEXT: int b = 1; +// CHECK-NEXT: int result = 1 * ((2.5) * (2.5)); +// CHECK-NEXT: ase_mmem_close_BBB(); +// CHECK-NEXT: return 0; +// CHECK-NEXT: } + +// CHECK: int b = ((0.5) * (0.5)); + +// CHECK: int c = 1 - 100; + +// CHECK: int d = 1 - 1; + +// CHECK: int main(void) { +// CHECK-NEXT: a = 1; +// CHECK-NEXT: int b = ((int_foo(&b)) * (int_foo(&b))); +// CHECK-NEXT: int e = (1 * ((2.5) * (2.5)) + int_foo(&b)) * 2; +// CHECK-NEXT: return 0; +// CHECK-NEXT: } + +// CHECK: #endif //NEW_CDF_DATAFRAME_TYPE_HBS