Implement the #define_other_target directive.

llvm-svn: 38984
This commit is contained in:
Chris Lattner 2006-10-14 19:54:15 +00:00
parent 58360339bd
commit 063400e46e
5 changed files with 75 additions and 8 deletions

View File

@ -209,6 +209,7 @@ IdentifierInfo &IdentifierTable::get(const char *NameStart,
Identifier->TokInfo.TokenID = tok::identifier;
Identifier->TokInfo.IsExtension = false;
Identifier->TokInfo.IsPoisoned = false;
Identifier->TokInfo.IsOtherTargetMacro = false;
Identifier->TokInfo.FETokenInfo = 0;
// Copy the string information.

View File

@ -106,6 +106,13 @@ static bool EvaluateValue(int &Result, LexerToken &PeekTok, DefinedTracker &DT,
PP.getTargetInfo().DiagnoseNonPortability(PeekTok.getLocation(),
diag::port_target_macro_use);
}
} else {
// Use of a target-specific macro for some other target? If so, warn.
if (II->isOtherTargetMacro()) {
II->setIsOtherTargetMacro(false); // Don't warn on second use.
PP.getTargetInfo().DiagnoseNonPortability(PeekTok.getLocation(),
diag::port_target_macro_use);
}
}
// Consume identifier.

View File

@ -1012,7 +1012,7 @@ void Preprocessor::HandleIdentifier(LexerToken &Identifier) {
}
// If this is a macro to be expanded, do it.
if (MacroInfo *MI = II.getMacroInfo())
if (MacroInfo *MI = II.getMacroInfo()) {
if (!DisableMacroExpansion && !Identifier.isExpandDisabled()) {
if (MI->isEnabled()) {
if (!HandleMacroExpandedIdentifier(Identifier, MI))
@ -1024,6 +1024,15 @@ void Preprocessor::HandleIdentifier(LexerToken &Identifier) {
Identifier.setFlag(LexerToken::DisableExpand);
}
}
} else if (II.isOtherTargetMacro() && !DisableMacroExpansion) {
// If this identifier is a macro on some other target, emit a diagnostic.
// This diagnosic is only emitted when macro expansion is enabled, because
// the macro would not have been expanded for the other target either.
II.setIsOtherTargetMacro(false); // Don't warn on second use.
getTargetInfo().DiagnoseNonPortability(Identifier.getLocation(),
diag::port_target_macro_use);
}
// Change the kind of this identifier to the appropriate token kind, e.g.
// turning "for" into a keyword.
@ -1467,6 +1476,10 @@ void Preprocessor::HandleDirective(LexerToken &Result) {
if (Directive[0] == 'd' && !strcmp(Directive, "define_target"))
return HandleDefineDirective(Result, true);
break;
case 19:
if (Directive[0] == 'd' && !strcmp(Directive, "define_other_target"))
return HandleDefineOtherTargetDirective(Result);
break;
}
break;
}
@ -1723,9 +1736,14 @@ void Preprocessor::HandleDefineDirective(LexerToken &DefineTok,
// mode.
CurLexer->KeepCommentMode = Features.KeepMacroComments;
// Create the new macro.
MacroInfo *MI = new MacroInfo(MacroNameTok.getLocation());
if (isTargetSpecific) MI->setIsTargetSpecific();
// If the identifier is an 'other target' macro, clear this bit.
MacroNameTok.getIdentifierInfo()->setIsOtherTargetMacro(false);
LexerToken Tok;
LexUnexpandedToken(Tok);
@ -1848,6 +1866,29 @@ void Preprocessor::HandleDefineDirective(LexerToken &DefineTok,
MacroNameTok.getIdentifierInfo()->setMacroInfo(MI);
}
/// HandleDefineOtherTargetDirective - Implements #define_other_target.
void Preprocessor::HandleDefineOtherTargetDirective(LexerToken &Tok) {
LexerToken MacroNameTok;
ReadMacroName(MacroNameTok, 1);
// Error reading macro name? If so, diagnostic already issued.
if (MacroNameTok.getKind() == tok::eom)
return;
// Check to see if this is the last token on the #undef line.
CheckEndOfDirective("#define_other_target");
// If there is already a macro defined by this name, turn it into a
// target-specific define.
if (MacroInfo *MI = MacroNameTok.getIdentifierInfo()->getMacroInfo()) {
MI->setIsTargetSpecific(true);
return;
}
// Mark the identifier as being a macro on some other target.
MacroNameTok.getIdentifierInfo()->setIsOtherTargetMacro();
}
/// HandleUndefDirective - Implements #undef.
///
@ -1867,6 +1908,9 @@ void Preprocessor::HandleUndefDirective(LexerToken &UndefTok) {
// Okay, we finally have a valid identifier to undef.
MacroInfo *MI = MacroNameTok.getIdentifierInfo()->getMacroInfo();
// #undef untaints an identifier if it were marked by define_other_target.
MacroNameTok.getIdentifierInfo()->setIsOtherTargetMacro(false);
// If the macro is not defined, this is a noop undef, just return.
if (MI == 0) return;
@ -1910,7 +1954,8 @@ void Preprocessor::HandleIfdefDirective(LexerToken &Result, bool isIfndef,
CurLexer->MIOpt.EnterTopLevelIFNDEF(MacroNameTok.getIdentifierInfo());
}
MacroInfo *MI = MacroNameTok.getIdentifierInfo()->getMacroInfo();
IdentifierInfo *MII = MacroNameTok.getIdentifierInfo();
MacroInfo *MI = MII->getMacroInfo();
// If there is a macro, process it.
if (MI) {
@ -1923,6 +1968,13 @@ void Preprocessor::HandleIfdefDirective(LexerToken &Result, bool isIfndef,
getTargetInfo().DiagnoseNonPortability(MacroNameTok.getLocation(),
diag::port_target_macro_use);
}
} else {
// Use of a target-specific macro for some other target? If so, warn.
if (MII->isOtherTargetMacro()) {
MII->setIsOtherTargetMacro(false); // Don't warn on second use.
getTargetInfo().DiagnoseNonPortability(MacroNameTok.getLocation(),
diag::port_target_macro_use);
}
}
// Should we include the stuff contained by this directive?

View File

@ -29,12 +29,13 @@ namespace clang {
/// variable or function name). The preprocessor keeps this information in a
/// set, and all tok::identifier tokens have a pointer to one of these.
class IdentifierInfo {
unsigned NameLen; // String that is the identifier.
MacroInfo *Macro; // Set if this identifier is #define'd.
tok::TokenKind TokenID:8; // Front-end token ID or tok::identifier.
bool IsExtension : 1; // True if this identifier is a language extension.
bool IsPoisoned : 1; // True if this identifier is poisoned.
void *FETokenInfo; // Managed by the language front-end.
unsigned NameLen; // String that is the identifier.
MacroInfo *Macro; // Set if this identifier is #define'd.
tok::TokenKind TokenID : 8; // Front-end token ID or tok::identifier.
bool IsExtension : 1; // True if identifier is a lang extension.
bool IsPoisoned : 1; // True if identifier is poisoned.
bool IsOtherTargetMacro : 1; // True if ident is a macro on another target.
void *FETokenInfo; // Managed by the language front-end.
friend class IdentifierTable;
public:
/// getName - Return the actual string for this identifier. The length of
@ -76,6 +77,11 @@ public:
/// isPoisoned - Return true if this token has been poisoned.
bool isPoisoned() const { return IsPoisoned; }
/// setIsOtherTargetMacro/isOtherTargetMacro control whether this identifier
/// is seen as being a macro on some other target.
void setIsOtherTargetMacro(bool Val = true) { IsOtherTargetMacro = Val; }
bool isOtherTargetMacro() const { return IsOtherTargetMacro; }
/// getFETokenInfo/setFETokenInfo - The language front-end is allowed to
/// associate arbitrary metadata with this token.
template<typename T>

View File

@ -534,6 +534,7 @@ private:
// Macro handling.
void HandleDefineDirective(LexerToken &Tok, bool isTargetSpecific);
void HandleUndefDirective(LexerToken &Tok);
void HandleDefineOtherTargetDirective(LexerToken &Tok);
// HandleAssertDirective(LexerToken &Tok);
// HandleUnassertDirective(LexerToken &Tok);