From: Chris Lattner Date: Mon, 13 Apr 2009 01:29:17 +0000 (+0000) Subject: implement the microsoft/gnu "__COUNTER__" macro: rdar://4329310 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c1f9d828c733ec1eba06d01070735d1f36fda733;p=clang implement the microsoft/gnu "__COUNTER__" macro: rdar://4329310 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68933 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index adce63c489..fa70cbf6fb 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -132,6 +132,8 @@ def ext_pp_base_file : Extension<"__BASE_FILE__ is a language extension">; def ext_pp_include_level : Extension< "__INCLUDE_LEVEL__ is a language extension">; def ext_pp_timestamp : Extension<"__TIMESTAMP__ is a language extension">; +def ext_pp_counter : Extension< + "__COUNTER__ is a language extension">; def err_pp_invalid_directive : Error<"invalid preprocessing directive">; def err_pp_hash_error : Error<"#error%0">; diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index dc8b6cc7c0..7782f36f43 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -165,8 +165,12 @@ namespace clang { PP_MACRO_FUNCTION_LIKE = 2, /// \brief Describes one token. - /// [PPTOKEN, SLoc, Length, IdentInfoID, Kind, Flags] - PP_TOKEN = 3 + /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags] + PP_TOKEN = 3, + + /// \brief The value of the next __COUNTER__ to dispense. + /// [PP_COUNTER_VALUE, Val] + PP_COUNTER_VALUE = 4 }; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 47f40b68f6..9e4278515b 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -67,9 +67,11 @@ class Preprocessor { IdentifierInfo *Ident__INCLUDE_LEVEL__; // __INCLUDE_LEVEL__ IdentifierInfo *Ident__BASE_FILE__; // __BASE_FILE__ IdentifierInfo *Ident__TIMESTAMP__; // __TIMESTAMP__ + IdentifierInfo *Ident__COUNTER__; // __COUNTER__ IdentifierInfo *Ident_Pragma, *Ident__VA_ARGS__; // _Pragma, __VA_ARGS__ SourceLocation DATELoc, TIMELoc; + unsigned CounterValue; // Next __COUNTER__ value. enum { /// MaxIncludeStackDepth - Maximum depth of #includes. @@ -590,6 +592,8 @@ public: bool SawDateOrTime() const { return DATELoc != SourceLocation() || TIMELoc != SourceLocation(); } + unsigned getCounterValue() const { return CounterValue; } + void setCounterValue(unsigned V) { CounterValue = V; } /// AllocateMacroInfo - Allocate a new MacroInfo object with the provide /// SourceLocation. diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index b916deaa69..fa6ad6f0a0 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -318,7 +318,11 @@ bool PCHReader::ReadPreprocessorBlock() { switch (RecType) { default: // Default behavior: ignore unknown records. break; - + case pch::PP_COUNTER_VALUE: + if (!Record.empty()) + PP.setCounterValue(Record[0]); + break; + case pch::PP_MACRO_OBJECT_LIKE: case pch::PP_MACRO_FUNCTION_LIKE: { IdentifierInfo *II = DecodeIdentifierInfo(Record[0]); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 6faf37fb29..2cf932ce9b 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -567,6 +567,13 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) { RecordData Record; + // If the preprocessor __COUNTER__ value has been bumped, remember it. + if (PP.getCounterValue() != 0) { + Record.push_back(PP.getCounterValue()); + S.EmitRecord(pch::PP_COUNTER_VALUE, Record); + Record.clear(); + } + // Loop over all the macro definitions that are live at the end of the file, // emitting each to the PP section. // FIXME: Eventually we want to emit an index so that we can lazily load @@ -627,9 +634,6 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) { } - // TODO: someday when PP supports __COUNTER__, emit a record for its value if - // non-zero. - S.ExitBlock(); } diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index b23311af19..797a5bf6f2 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -55,6 +55,7 @@ void Preprocessor::RegisterBuiltinMacros() { Ident__FILE__ = RegisterBuiltinMacro("__FILE__"); Ident__DATE__ = RegisterBuiltinMacro("__DATE__"); Ident__TIME__ = RegisterBuiltinMacro("__TIME__"); + Ident__COUNTER__ = RegisterBuiltinMacro("__COUNTER__"); Ident_Pragma = RegisterBuiltinMacro("_Pragma"); // GCC Extensions. @@ -557,6 +558,13 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { TmpBuffer[Len] = '"'; // Replace the newline with a quote. Tok.setKind(tok::string_literal); CreateString(TmpBuffer, Len+1, Tok, Tok.getLocation()); + } else if (II == Ident__COUNTER__) { + Diag(Tok, diag::ext_pp_counter); + + // __COUNTER__ expands to a simple numeric value. + sprintf(TmpBuffer, "%u", CounterValue++); + Tok.setKind(tok::numeric_constant); + CreateString(TmpBuffer, strlen(TmpBuffer), Tok, Tok.getLocation()); } else { assert(0 && "Unknown identifier!"); } diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 097b4542b6..2c9b0b937a 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -53,7 +53,8 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts, SourceMgr(SM), HeaderInfo(Headers), Identifiers(opts, IILookup), CurPPLexer(0), CurDirLookup(0), Callbacks(0) { ScratchBuf = new ScratchBuffer(SourceMgr); - + CounterValue = 0; // __COUNTER__ starts at 0. + // Clear stats. NumDirectives = NumDefined = NumUndefined = NumPragma = 0; NumIf = NumElse = NumEndif = 0; diff --git a/test/Lexer/counter.c b/test/Lexer/counter.c new file mode 100644 index 0000000000..9b2c2c7434 --- /dev/null +++ b/test/Lexer/counter.c @@ -0,0 +1,16 @@ +// __COUNTER__ support: rdar://4329310 +// RUN: clang -E %s > %t && + +#define PASTE2(x,y) x##y +#define PASTE1(x,y) PASTE2(x,y) +#define UNIQUE(x) PASTE1(x,__COUNTER__) + +// RUN: grep "A: 0" %t && +A: __COUNTER__ + +// RUN: grep "B: foo1" %t && +B: UNIQUE(foo); +// RUN: grep "C: foo2" %t && +C: UNIQUE(foo); +// RUN: grep "D: 3" %t +D: __COUNTER__ diff --git a/test/PCH/variables.c b/test/PCH/variables.c index 749b7b6741..f725e7d8f0 100644 --- a/test/PCH/variables.c +++ b/test/PCH/variables.c @@ -15,4 +15,8 @@ double z; // expected-error{{redefinition}} int Q = A_MACRO_IN_THE_PCH; -int R = FUNCLIKE_MACRO(A_MACRO_, IN_THE_PCH); \ No newline at end of file +int R = FUNCLIKE_MACRO(A_MACRO_, IN_THE_PCH); + + +int UNIQUE(a); // a2 +int *Arr[] = { &a0, &a1, &a2 }; diff --git a/test/PCH/variables.h b/test/PCH/variables.h index 7b27671328..82e87aaf4b 100644 --- a/test/PCH/variables.h +++ b/test/PCH/variables.h @@ -16,3 +16,11 @@ int MAKE_HAPPY(Very); #define A_MACRO_IN_THE_PCH 492 #define FUNCLIKE_MACRO(X, Y) X ## Y + +#define PASTE2(x,y) x##y +#define PASTE1(x,y) PASTE2(x,y) +#define UNIQUE(x) PASTE1(x,__COUNTER__) + +int UNIQUE(a); // a0 +int UNIQUE(a); // a1 +