Add support for target-independent builtin functions (like __builtin_abs),

whose decl objects are lazily created the first time they are referenced.
Builtin functions are described by the clang/AST/Builtins.def file, which
makes it easy to add new ones.

This is missing two important pieces:
1. Support for the rest of the gcc builtins.
2. Support for target-specific builtins (e.g. __builtin_ia32_emms).

Just adding this builtins reduces the number of implicit function definitions
by 6, reducing the # diagnostics from 550 to 544 when parsing carbon.h.

I need to add all the i386-specific ones to eliminate several hundred more.
ugh.

llvm-svn: 39327
This commit is contained in:
Chris Lattner 2007-01-28 08:20:04 +00:00
parent b6738ec361
commit 9561a0b3e7
14 changed files with 382 additions and 28 deletions

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "clang/AST/Builtins.h"
#include "clang/AST/Decl.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/SmallVector.h"
@ -21,6 +22,7 @@ using namespace clang;
ASTContext::ASTContext(Preprocessor &pp)
: PP(pp), Target(pp.getTargetInfo()) {
InitBuiltinTypes();
Builtin::InitializeBuiltins(PP.getIdentifierTable(), Target);
}
ASTContext::~ASTContext() {

112
clang/AST/Builtins.cpp Normal file
View File

@ -0,0 +1,112 @@
//===--- Builtins.cpp - Builtin function implementation -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements various things for builtin functions.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/Builtins.h"
#include "clang/AST/ASTContext.h"
#include "clang/Lex/IdentifierTable.h"
using namespace llvm;
using namespace clang;
static const Builtin::Info BuiltinInfo[] = {
{ "not a builtin function", 0, 0 },
#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS },
#include "clang/AST/Builtins.def"
};
/// Builtin::GetName - Return the identifier name for the specified builtin,
/// e.g. "__builtin_abs".
const char *Builtin::GetName(ID id) {
if (id >= Builtin::FirstTargetSpecificBuiltin)
return "target-builtin";
return BuiltinInfo[id].Name;
}
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
void Builtin::InitializeBuiltins(IdentifierTable &Table,
const TargetInfo &Target) {
// Step #1: mark all target-independent builtins with their ID's.
for (unsigned i = Builtin::NotBuiltin+1;
i != Builtin::FirstTargetSpecificBuiltin; ++i)
Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
// Step #2: handle target builtins.
// FIXME: implement.
}
/// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the
/// pointer over the consumed characters. This returns the resultant type.
static TypeRef DecodeTypeFromStr(const char *&Str, ASTContext &Context) {
// Modifiers.
bool Long = false, LongLong = false, Signed = false, Unsigned = false;
// Read the modifiers first.
bool Done = false;
while (!Done) {
switch (*Str++) {
default: Done = true; --Str; break;
case 'S':
assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!");
assert(!Signed && "Can't use 'S' modifier multiple times!");
Signed = true;
break;
case 'U':
assert(!Signed && "Can't use both 'S' and 'U' modifiers!");
assert(!Unsigned && "Can't use 'S' modifier multiple times!");
Unsigned = true;
break;
case 'L':
assert(!LongLong && "Can't have LLL modifier");
if (Long)
LongLong = true;
else
Long = true;
break;
}
}
// Read the base type.
switch (*Str++) {
default: assert(0 && "Unknown builtin type letter!");
case 'f':
assert(!Long && !Signed && !Unsigned && "Bad modifiers used with 'f'!");
return Context.FloatTy;
case 'd':
assert(!LongLong && !Signed && !Unsigned && "Bad modifiers used with 'd'!");
if (Long)
return Context.LongDoubleTy;
return Context.DoubleTy;
//case 'i':
}
}
/// GetBuiltinType - Return the type for the specified builtin.
TypeRef Builtin::GetBuiltinType(ID id, ASTContext &Context) {
assert(id < Builtin::FirstTargetSpecificBuiltin &&
"Can't handle target builtins yet!");
const char *TypeStr = BuiltinInfo[id].Type;
SmallVector<TypeRef, 8> ArgTypes;
TypeRef ResType = DecodeTypeFromStr(TypeStr, Context);
while (TypeStr[0] && TypeStr[0] != '.')
ArgTypes.push_back(DecodeTypeFromStr(TypeStr, Context));
assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
"'.' should only occur at end of builtin type list!");
return Context.getFunctionType(ResType, &ArgTypes[0], ArgTypes.size(),
TypeStr[0] == '.');
}

View File

@ -74,7 +74,10 @@ public:
virtual DeclTy *ParseStartOfFunctionDef(Scope *S, Declarator &D);
virtual DeclTy *ParseFunctionDefBody(DeclTy *Decl, StmtTy *Body);
virtual void PopScope(SourceLocation Loc, Scope *S);
Decl *LookupScopedDecl(IdentifierInfo *II, unsigned NSI);
Decl *LookupScopedDecl(IdentifierInfo *II, unsigned NSI, SourceLocation IdLoc,
Scope *S);
Decl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S);
TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D);
TypedefDecl *MergeTypeDefDecl(TypedefDecl *New, Decl *Old);

View File

@ -13,6 +13,7 @@
#include "Sema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Builtins.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
@ -20,6 +21,7 @@
#include "clang/Parse/Scope.h"
#include "clang/Lex/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallSet.h"
using namespace llvm;
using namespace clang;
@ -69,7 +71,8 @@ void Sema::PopScope(SourceLocation Loc, Scope *S) {
/// LookupScopedDecl - Look up the inner-most declaration in the specified
/// namespace.
Decl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI) {
Decl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI,
SourceLocation IdLoc, Scope *S) {
if (II == 0) return 0;
Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI;
@ -80,10 +83,56 @@ Decl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI) {
if (D->getIdentifierNamespace() == NS)
return D;
// If we didn't find a use of this identifier, and if the identifier
// corresponds to a compiler builtin, create the decl object for the builtin
// now, injecting it into translation unit scope, and return it.
if (NS == Decl::IDNS_Ordinary) {
// If this is a builtin on some other target, or if this builtin varies
// across targets (e.g. in type), emit a diagnostic and mark the translation
// unit non-portable for using it.
if (II->isNonPortableBuiltin()) {
// Only emit this diagnostic once for this builtin.
II->setNonPortableBuiltin(false);
Context.Target.DiagnoseNonPortability(IdLoc,
diag::port_target_builtin_use);
}
// If this is a builtin on this (or all) targets, create the decl.
if (unsigned BuiltinID = II->getBuiltinID())
return LazilyCreateBuiltin(II, BuiltinID, S);
}
return 0;
}
/// LazilyCreateBuiltin - The specified Builtin-ID was first used at file scope.
/// lazily create a decl for it.
Decl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Scope *S) {
Builtin::ID BID = (Builtin::ID)bid;
TypeRef R = Builtin::GetBuiltinType(BID, Context);
FunctionDecl *New = new FunctionDecl(SourceLocation(), II, R);
// Find translation-unit scope to insert this function into.
while (S->getParent())
S = S->getParent();
S->AddDecl(New);
// Add this decl to the end of the identifier info.
if (Decl *LastDecl = II->getFETokenInfo<Decl>()) {
// Scan until we find the last (outermost) decl in the id chain.
while (LastDecl->getNext())
LastDecl = LastDecl->getNext();
// Insert before (outside) it.
LastDecl->setNext(New);
} else {
II->setFETokenInfo(New);
}
// Make sure clients iterating over decls see this.
LastInGroupList.push_back(New);
return New;
}
/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the same name
/// and scope as a previous declaration 'Old'. Figure out how to resolve this
/// situation, merging decls or emitting diagnostics as appropriate.
@ -174,7 +223,8 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
IdentifierInfo *II = D.getIdentifier();
// See if this is a redefinition of a variable in the same scope.
Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary);
Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary,
D.getIdentifierLoc(), S);
if (!S->isDeclScope(PrevDecl))
PrevDecl = 0; // If in outer scope, it isn't the same thing.
@ -239,7 +289,8 @@ Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
// TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
// Can this happen for params? We already checked that they don't conflict
// among each other. Here they can only shadow globals, which is ok.
if (Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary)) {
if (Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary,
PI.IdentLoc, FnScope)) {
}
@ -382,7 +433,8 @@ Sema::DeclTy *Sema::ParseTag(Scope *S, unsigned TagType, TagKind TK,
// If this is a named struct, check to see if there was a previous forward
// declaration or definition.
if (TagDecl *PrevDecl =
dyn_cast_or_null<TagDecl>(LookupScopedDecl(Name, Decl::IDNS_Tag))) {
dyn_cast_or_null<TagDecl>(LookupScopedDecl(Name, Decl::IDNS_Tag,
NameLoc, S))) {
// If this is a use of a previous tag, or if the tag is already declared in
// the same scope (so that the definition/declaration completes or
@ -604,7 +656,7 @@ Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *EnumDeclX,
// Verify that there isn't already something declared with this name in this
// scope.
if (Decl *PrevDecl = LookupScopedDecl(Id, Decl::IDNS_Ordinary)) {
if (Decl *PrevDecl = LookupScopedDecl(Id, Decl::IDNS_Ordinary, IdLoc, S)) {
if (S->isDeclScope(PrevDecl)) {
if (isa<EnumConstantDecl>(PrevDecl))
Diag(IdLoc, diag::err_redefinition_of_enumerator, Id->getName());

View File

@ -247,14 +247,10 @@ Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc,
IdentifierInfo &II,
bool HasTrailingLParen) {
// Could be enum-constant or decl.
Decl *D = II.getFETokenInfo<Decl>();
Decl *D = LookupScopedDecl(&II, Decl::IDNS_Ordinary, Loc, S);
if (D == 0) {
// FIXME: check to see if this is a use of a builtin. By handling builtins
// here, we can avoid having to preload tons of decls for functions.
// Otherwise, this is an imlicitly declared function reference (legal in
// C90, extension in C99).
// Otherwise, this could be an imlicitly declared function reference (legal
// in C90, extension in C99).
if (HasTrailingLParen &&
// Not in C++.
!getLangOptions().CPlusPlus) {

View File

@ -28,6 +28,7 @@ IdentifierInfo::IdentifierInfo() {
TokenID = tok::identifier;
PPID = tok::pp_not_keyword;
ObjCID = tok::objc_not_keyword;
BuiltinID = 0;
IsExtension = false;
IsPoisoned = false;
IsOtherTargetMacro = false;

View File

@ -74,7 +74,10 @@ public:
virtual DeclTy *ParseStartOfFunctionDef(Scope *S, Declarator &D);
virtual DeclTy *ParseFunctionDefBody(DeclTy *Decl, StmtTy *Body);
virtual void PopScope(SourceLocation Loc, Scope *S);
Decl *LookupScopedDecl(IdentifierInfo *II, unsigned NSI);
Decl *LookupScopedDecl(IdentifierInfo *II, unsigned NSI, SourceLocation IdLoc,
Scope *S);
Decl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S);
TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D);
TypedefDecl *MergeTypeDefDecl(TypedefDecl *New, Decl *Old);

View File

@ -13,6 +13,7 @@
#include "Sema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Builtins.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
@ -20,6 +21,7 @@
#include "clang/Parse/Scope.h"
#include "clang/Lex/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallSet.h"
using namespace llvm;
using namespace clang;
@ -69,7 +71,8 @@ void Sema::PopScope(SourceLocation Loc, Scope *S) {
/// LookupScopedDecl - Look up the inner-most declaration in the specified
/// namespace.
Decl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI) {
Decl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI,
SourceLocation IdLoc, Scope *S) {
if (II == 0) return 0;
Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI;
@ -80,10 +83,56 @@ Decl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI) {
if (D->getIdentifierNamespace() == NS)
return D;
// If we didn't find a use of this identifier, and if the identifier
// corresponds to a compiler builtin, create the decl object for the builtin
// now, injecting it into translation unit scope, and return it.
if (NS == Decl::IDNS_Ordinary) {
// If this is a builtin on some other target, or if this builtin varies
// across targets (e.g. in type), emit a diagnostic and mark the translation
// unit non-portable for using it.
if (II->isNonPortableBuiltin()) {
// Only emit this diagnostic once for this builtin.
II->setNonPortableBuiltin(false);
Context.Target.DiagnoseNonPortability(IdLoc,
diag::port_target_builtin_use);
}
// If this is a builtin on this (or all) targets, create the decl.
if (unsigned BuiltinID = II->getBuiltinID())
return LazilyCreateBuiltin(II, BuiltinID, S);
}
return 0;
}
/// LazilyCreateBuiltin - The specified Builtin-ID was first used at file scope.
/// lazily create a decl for it.
Decl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Scope *S) {
Builtin::ID BID = (Builtin::ID)bid;
TypeRef R = Builtin::GetBuiltinType(BID, Context);
FunctionDecl *New = new FunctionDecl(SourceLocation(), II, R);
// Find translation-unit scope to insert this function into.
while (S->getParent())
S = S->getParent();
S->AddDecl(New);
// Add this decl to the end of the identifier info.
if (Decl *LastDecl = II->getFETokenInfo<Decl>()) {
// Scan until we find the last (outermost) decl in the id chain.
while (LastDecl->getNext())
LastDecl = LastDecl->getNext();
// Insert before (outside) it.
LastDecl->setNext(New);
} else {
II->setFETokenInfo(New);
}
// Make sure clients iterating over decls see this.
LastInGroupList.push_back(New);
return New;
}
/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the same name
/// and scope as a previous declaration 'Old'. Figure out how to resolve this
/// situation, merging decls or emitting diagnostics as appropriate.
@ -174,7 +223,8 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
IdentifierInfo *II = D.getIdentifier();
// See if this is a redefinition of a variable in the same scope.
Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary);
Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary,
D.getIdentifierLoc(), S);
if (!S->isDeclScope(PrevDecl))
PrevDecl = 0; // If in outer scope, it isn't the same thing.
@ -239,7 +289,8 @@ Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
// TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
// Can this happen for params? We already checked that they don't conflict
// among each other. Here they can only shadow globals, which is ok.
if (Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary)) {
if (Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary,
PI.IdentLoc, FnScope)) {
}
@ -382,7 +433,8 @@ Sema::DeclTy *Sema::ParseTag(Scope *S, unsigned TagType, TagKind TK,
// If this is a named struct, check to see if there was a previous forward
// declaration or definition.
if (TagDecl *PrevDecl =
dyn_cast_or_null<TagDecl>(LookupScopedDecl(Name, Decl::IDNS_Tag))) {
dyn_cast_or_null<TagDecl>(LookupScopedDecl(Name, Decl::IDNS_Tag,
NameLoc, S))) {
// If this is a use of a previous tag, or if the tag is already declared in
// the same scope (so that the definition/declaration completes or
@ -604,7 +656,7 @@ Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *EnumDeclX,
// Verify that there isn't already something declared with this name in this
// scope.
if (Decl *PrevDecl = LookupScopedDecl(Id, Decl::IDNS_Ordinary)) {
if (Decl *PrevDecl = LookupScopedDecl(Id, Decl::IDNS_Ordinary, IdLoc, S)) {
if (S->isDeclScope(PrevDecl)) {
if (isa<EnumConstantDecl>(PrevDecl))
Diag(IdLoc, diag::err_redefinition_of_enumerator, Id->getName());

View File

@ -247,14 +247,10 @@ Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc,
IdentifierInfo &II,
bool HasTrailingLParen) {
// Could be enum-constant or decl.
Decl *D = II.getFETokenInfo<Decl>();
Decl *D = LookupScopedDecl(&II, Decl::IDNS_Ordinary, Loc, S);
if (D == 0) {
// FIXME: check to see if this is a use of a builtin. By handling builtins
// here, we can avoid having to preload tons of decls for functions.
// Otherwise, this is an imlicitly declared function reference (legal in
// C90, extension in C99).
// Otherwise, this could be an imlicitly declared function reference (legal
// in C90, extension in C99).
if (HasTrailingLParen &&
// Not in C++.
!getLangOptions().CPlusPlus) {

View File

@ -57,6 +57,9 @@
DED626C90AE0C065001E80A4 /* TargetInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED626C80AE0C065001E80A4 /* TargetInfo.cpp */; };
DED627030AE0C51D001E80A4 /* Targets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED627020AE0C51D001E80A4 /* Targets.cpp */; };
DED62ABB0AE2EDF1001E80A4 /* Decl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED62ABA0AE2EDF1001E80A4 /* Decl.cpp */; };
DED676D10B6C786700AAD4A3 /* Builtins.def in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED676D00B6C786700AAD4A3 /* Builtins.def */; };
DED676FA0B6C797B00AAD4A3 /* Builtins.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED676F90B6C797B00AAD4A3 /* Builtins.h */; };
DED677C90B6C854100AAD4A3 /* Builtins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED677C80B6C854100AAD4A3 /* Builtins.cpp */; };
DED7D7410A524295003AD0FB /* Diagnostic.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7310A524295003AD0FB /* Diagnostic.h */; };
DED7D7420A524295003AD0FB /* DiagnosticKinds.def in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7320A524295003AD0FB /* DiagnosticKinds.def */; };
DED7D7430A524295003AD0FB /* FileManager.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7330A524295003AD0FB /* FileManager.h */; };
@ -134,6 +137,8 @@
DE75ED290B044DC90020CF81 /* ASTContext.h in CopyFiles */,
DE1733700B068DC60080B521 /* DeclSpec.h in CopyFiles */,
DE01DA490B12ADA300AC22CE /* PPCallbacks.h in CopyFiles */,
DED676D10B6C786700AAD4A3 /* Builtins.def in CopyFiles */,
DED676FA0B6C797B00AAD4A3 /* Builtins.h in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
@ -191,6 +196,9 @@
DED626C80AE0C065001E80A4 /* TargetInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TargetInfo.cpp; sourceTree = "<group>"; };
DED627020AE0C51D001E80A4 /* Targets.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Targets.cpp; path = Driver/Targets.cpp; sourceTree = "<group>"; };
DED62ABA0AE2EDF1001E80A4 /* Decl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Decl.cpp; path = AST/Decl.cpp; sourceTree = "<group>"; };
DED676D00B6C786700AAD4A3 /* Builtins.def */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = Builtins.def; path = clang/AST/Builtins.def; sourceTree = "<group>"; };
DED676F90B6C797B00AAD4A3 /* Builtins.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Builtins.h; path = clang/AST/Builtins.h; sourceTree = "<group>"; };
DED677C80B6C854100AAD4A3 /* Builtins.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Builtins.cpp; path = AST/Builtins.cpp; sourceTree = "<group>"; };
DED7D7310A524295003AD0FB /* Diagnostic.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Diagnostic.h; sourceTree = "<group>"; };
DED7D7320A524295003AD0FB /* DiagnosticKinds.def */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = DiagnosticKinds.def; sourceTree = "<group>"; };
DED7D7330A524295003AD0FB /* FileManager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FileManager.h; sourceTree = "<group>"; };
@ -317,6 +325,8 @@
DEC8D9A30A94346E00353FCA /* AST.h */,
DE75ED280B044DC90020CF81 /* ASTContext.h */,
DEC8DABF0A94402500353FCA /* ASTStreamer.h */,
DED676D00B6C786700AAD4A3 /* Builtins.def */,
DED676F90B6C797B00AAD4A3 /* Builtins.h */,
DEC8D9900A9433CD00353FCA /* Decl.h */,
DE0FCA620A95859D00248FD5 /* Expr.h */,
DE3452800AEF1B1800DBC861 /* Stmt.h */,
@ -332,6 +342,7 @@
children = (
DE1732FF0B068B700080B521 /* ASTContext.cpp */,
DEC8DAAC0A94400300353FCA /* ASTStreamer.cpp */,
DED677C80B6C854100AAD4A3 /* Builtins.cpp */,
DED62ABA0AE2EDF1001E80A4 /* Decl.cpp */,
DE0FCB330A9C21F100248FD5 /* Expr.cpp */,
DE3452400AEF1A2D00DBC861 /* Stmt.cpp */,
@ -507,6 +518,7 @@
DE1733000B068B700080B521 /* ASTContext.cpp in Sources */,
DE17336E0B068DC20080B521 /* DeclSpec.cpp in Sources */,
DE1737A90B0847BC0080B521 /* SemaType.cpp in Sources */,
DED677C90B6C854100AAD4A3 /* Builtins.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -0,0 +1,52 @@
//===--- Builtins.def - Builtin function info database ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the standard builtin function database. Users of this file
// must define the BUILTIN macro to make use of this information.
//
//===----------------------------------------------------------------------===//
// FIXME: this needs to be the full list supported by GCC. Right now, I'm just
// adding stuff on demand.
//
// FIXME: This should really be a .td file, but that requires modifying tblgen.
// Perhaps tblgen should have plugins.
// The first value provided to the macro specifies the function name of the
// builtin, and results in a clang::builtin::BIXX enum value for XX.
// The second value provided to the macro specifies the type of the function
// (result value, then each argument) as follows:
// v -> void
// c -> char
// s -> short
// i -> int
// f -> float
// d -> double
// . -> "...". This may only occur at the end of the function list.
//
// Types maybe prefixed with the following modifiers:
// L -> long (e.g. Li for 'long int')
// LL -> long long
// S -> signed
// U -> unsigned
// The third value provided to the macro specifies information about attributes
// of the function. Currently we have:
// n -> nothrow
// c -> const
BUILTIN(__builtin_inf , "d" , "nc")
BUILTIN(__builtin_inff , "f" , "nc")
BUILTIN(__builtin_infl , "Ld" , "nc")
BUILTIN(__builtin_fabs , "dd" , "nc")
BUILTIN(__builtin_fabsf, "ff" , "nc")
BUILTIN(__builtin_fabsl, "LdLd", "nc")
#undef BUILTIN

View File

@ -0,0 +1,52 @@
//===--- Builtins.h - Builtin function header -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines enum values for all the target-independent builtin
// functions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_BUILTINS_H
#define LLVM_CLANG_AST_BUILTINS_H
namespace llvm {
namespace clang {
class TargetInfo;
class IdentifierTable;
class ASTContext;
class TypeRef;
namespace Builtin {
enum ID {
NotBuiltin = 0, // This is not a builtin function.
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
#include "clang/AST/Builtins.def"
FirstTargetSpecificBuiltin
};
struct Info {
const char *Name, *Type, *Attributes;
};
/// Builtin::GetName - Return the identifier name for the specified builtin,
/// e.g. "__builtin_abs".
const char *GetName(ID id);
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
void InitializeBuiltins(IdentifierTable &Table, const TargetInfo &Target);
/// GetBuiltinType - Return the type for the specified builtin.
TypeRef GetBuiltinType(ID id, ASTContext &Context);
}
} // end namespace clang
} // end namespace llvm
#endif

View File

@ -27,6 +27,9 @@
DIAG(port_target_macro_use, NOTE,
"use of a target-specific macro, source is not 'portable'")
DIAG(port_target_builtin_use, NOTE,
"use of a target-specific builtin function, source is not 'portable'")
DIAG(port_wchar_t, NOTE,
"sizeof(wchar_t) varies between targets, source is not 'portable'")

View File

@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_IDENTIFIERTABLE_H
#define LLVM_CLANG_IDENTIFIERTABLE_H
#ifndef LLVM_CLANG_LEX_IDENTIFIERTABLE_H
#define LLVM_CLANG_LEX_IDENTIFIERTABLE_H
#include "clang/Basic/TokenKinds.h"
#include "llvm/ADT/CStringMap.h"
@ -33,10 +33,12 @@ class IdentifierInfo {
tok::TokenKind TokenID : 8; // Front-end token ID or tok::identifier.
tok::PPKeywordKind PPID : 5; // ID for preprocessor command like #'ifdef'.
tok::ObjCKeywordKind ObjCID : 5; // ID for objc @ keyword like @'protocol'.
unsigned BuiltinID :12; // ID if this is a builtin (__builtin_inf).
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 macro on another target.
bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
bool IsNonPortableBuiltin : 1; // True if builtin varies across targets.
void *FETokenInfo; // Managed by the language front-end.
IdentifierInfo(const IdentifierInfo&); // NONCOPYABLE.
public:
@ -74,6 +76,22 @@ public:
tok::ObjCKeywordKind getObjCKeywordID() const { return ObjCID; }
void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCID = ID; }
/// getBuiltinID - Return a value indicating whether this is a builtin
/// function. 0 is not-built-in. 1 is builtin-for-some-nonprimary-target.
/// 2+ are specific builtin functions.
unsigned getBuiltinID() const { return BuiltinID; }
void setBuiltinID(unsigned ID) {
assert(ID < (1 << 12) && "ID too large for field!");
BuiltinID = ID;
}
/// isNonPortableBuiltin - Return true if this identifier corresponds to a
/// builtin on some other target, but isn't one on this target, or if it is on
/// the target but not on another, or if it is on both but it differs somehow
/// in behavior.
bool isNonPortableBuiltin() const { return IsNonPortableBuiltin; }
void setNonPortableBuiltin(bool Val) { IsNonPortableBuiltin = Val; }
/// get/setExtension - Initialize information about whether or not this
/// language token is an extension. This controls extension warnings, and is
/// only valid if a custom token ID is set.