Update clang to r98631.

This commit is contained in:
Roman Divacky 2010-03-16 16:52:15 +00:00
parent a16e9ac1f1
commit 4a37f65f1c
169 changed files with 5632 additions and 3076 deletions

View File

@ -39,19 +39,19 @@ cscope.files:
install-local::
$(Echo) Installing include files
$(Verb) $(MKDIR) $(PROJ_includedir)
$(Verb) $(MKDIR) $(DESTDIR)$(PROJ_includedir)
$(Verb) if test -d "$(PROJ_SRC_ROOT)/tools/clang/include" ; then \
cd $(PROJ_SRC_ROOT)/tools/clang/include && \
for hdr in `find . -type f '!' '(' -name '*~' \
-o -name '.#*' -o -name '*.in' -o -name '*.txt' \
-o -name 'Makefile' -o -name '*.td' ')' -print \
| grep -v CVS | grep -v .svn | grep -v .dir` ; do \
instdir=`dirname "$(PROJ_includedir)/$$hdr"` ; \
instdir=$(DESTDIR)`dirname "$(PROJ_includedir)/$$hdr"` ; \
if test \! -d "$$instdir" ; then \
$(EchoCmd) Making install directory $$instdir ; \
$(MKDIR) $$instdir ;\
fi ; \
$(DataInstall) $$hdr $(PROJ_includedir)/$$hdr ; \
$(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \
done ; \
fi
ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
@ -59,7 +59,7 @@ ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
cd $(PROJ_OBJ_ROOT)/tools/clang/include && \
for hdr in `find . -type f '!' '(' -name 'Makefile' ')' -print \
| grep -v CVS | grep -v .tmp | grep -v .dir` ; do \
$(DataInstall) $$hdr $(PROJ_includedir)/$$hdr ; \
$(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \
done ; \
fi
endif

View File

@ -49,6 +49,7 @@
1A81AA19108144F40094E50B /* CGVtable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A81AA18108144F40094E50B /* CGVtable.cpp */; };
1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */; };
1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; };
1A96785211486FDC00F24372 /* RecordLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A96785111486FDC00F24372 /* RecordLayout.cpp */; };
1A97825B1108BA18002B98FC /* CGVTT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A97825A1108BA18002B98FC /* CGVTT.cpp */; };
1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */; };
1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */; };
@ -420,6 +421,7 @@
1A81AA5D108278A20094E50B /* CGVtable.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGVtable.h; path = lib/CodeGen/CGVtable.h; sourceTree = "<group>"; tabWidth = 2; };
1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = "<group>"; };
1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
1A96785111486FDC00F24372 /* RecordLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = RecordLayout.cpp; path = lib/AST/RecordLayout.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A97825A1108BA18002B98FC /* CGVTT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGVTT.cpp; path = lib/CodeGen/CGVTT.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGDeclCXX.cpp; path = lib/CodeGen/CGDeclCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = RecordLayoutBuilder.cpp; path = lib/AST/RecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
@ -1438,6 +1440,7 @@
3557D1A80EB136B100C59739 /* InheritViz.cpp */,
DEDFE5CE0F7206E40035BD10 /* NestedNameSpecifier.cpp */,
35EE48B00E0C4CCA00715C54 /* ParentMap.cpp */,
1A96785111486FDC00F24372 /* RecordLayout.cpp */,
1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */,
1AA1D91710125DE30078DEBC /* RecordLayoutBuilder.h */,
DE3452400AEF1A2D00DBC861 /* Stmt.cpp */,
@ -1993,6 +1996,7 @@
1A621C4411111D61009E6834 /* CIndexInclusionStack.cpp in Sources */,
1A621C4511111D61009E6834 /* CIndexUSRs.cpp in Sources */,
1A621C4611111D61009E6834 /* CXCursor.cpp in Sources */,
1A96785211486FDC00F24372 /* RecordLayout.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -171,7 +171,7 @@ CINDEX_LINKAGE void clang_disposeString(CXString string);
*/
CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
int displayDiagnostics);
/**
* \brief Destroy the given index.
*
@ -297,7 +297,7 @@ CINDEX_LINKAGE CXSourceLocation clang_getLocation(CXTranslationUnit tu,
* \brief Retrieve a NULL (invalid) source range.
*/
CINDEX_LINKAGE CXSourceRange clang_getNullRange();
/**
* \brief Retrieve a source range given the beginning and ending source
* locations.
@ -357,11 +357,11 @@ CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range);
*/
enum CXDiagnosticSeverity {
/**
* \brief A diagnostic that has been suppressed, e.g., by a command-line
* \brief A diagnostic that has been suppressed, e.g., by a command-line
* option.
*/
CXDiagnostic_Ignored = 0,
/**
* \brief This diagnostic is a note that should be attached to the
* previous (non-note) diagnostic.
@ -451,7 +451,7 @@ enum CXDiagnosticDisplayOptions {
* diagnostic, also include information about source ranges in a
* machine-parsable format.
*
* This option corresponds to the clang flag
* This option corresponds to the clang flag
* \c -fdiagnostics-print-source-range-info.
*/
CXDiagnostic_DisplaySourceRanges = 0x04
@ -461,13 +461,13 @@ enum CXDiagnosticDisplayOptions {
* \brief Format the given diagnostic in a manner that is suitable for display.
*
* This routine will format the given diagnostic to a string, rendering
* the diagnostic according to the various options given. The
* \c clang_defaultDiagnosticDisplayOptions() function returns the set of
* the diagnostic according to the various options given. The
* \c clang_defaultDiagnosticDisplayOptions() function returns the set of
* options that most closely mimics the behavior of the clang compiler.
*
* \param Diagnostic The diagnostic to print.
*
* \param Options A set of options that control the diagnostic display,
* \param Options A set of options that control the diagnostic display,
* created by combining \c CXDiagnosticDisplayOptions values.
*
* \returns A new string containing for formatted diagnostic.
@ -491,7 +491,7 @@ CINDEX_LINKAGE unsigned clang_defaultDiagnosticDisplayOptions(void);
/**
* \brief Determine the severity of the given diagnostic.
*/
CINDEX_LINKAGE enum CXDiagnosticSeverity
CINDEX_LINKAGE enum CXDiagnosticSeverity
clang_getDiagnosticSeverity(CXDiagnostic);
/**
@ -512,21 +512,21 @@ CINDEX_LINKAGE CXString clang_getDiagnosticSpelling(CXDiagnostic);
* diagnostic.
*/
CINDEX_LINKAGE unsigned clang_getDiagnosticNumRanges(CXDiagnostic);
/**
* \brief Retrieve a source range associated with the diagnostic.
*
* A diagnostic's source ranges highlight important elements in the source
* code. On the command line, Clang displays source ranges by
* underlining them with '~' characters.
* underlining them with '~' characters.
*
* \param Diagnostic the diagnostic whose range is being extracted.
*
* \param Range the zero-based index specifying which range to
* \param Range the zero-based index specifying which range to
*
* \returns the requested source range.
*/
CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic,
CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic,
unsigned Range);
/**
@ -560,7 +560,7 @@ CINDEX_LINKAGE unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic);
* \returns A string containing text that should be replace the source
* code indicated by the \c ReplacementRange.
*/
CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic,
CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic,
unsigned FixIt,
CXSourceRange *ReplacementRange);
@ -577,7 +577,7 @@ CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic,
*
* @{
*/
/**
* \brief Get the original translation unit source file name.
*/
@ -625,22 +625,22 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
const char **clang_command_line_args,
unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files);
/**
* \brief Create a translation unit from an AST file (-emit-ast).
*/
CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex,
CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex,
const char *ast_filename);
/**
* \brief Destroy the specified CXTranslationUnit object.
*/
CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
/**
* @}
*/
/**
* \brief Describes the kind of entity that a cursor refers to.
*/
@ -1082,6 +1082,47 @@ CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent,
*/
CINDEX_LINKAGE CXString clang_getCursorUSR(CXCursor);
/**
* \brief Construct a USR for a specified Objective-C class.
*/
CINDEX_LINKAGE CXString clang_constructUSR_ObjCClass(const char *class_name);
/**
* \brief Construct a USR for a specified Objective-C category.
*/
CINDEX_LINKAGE CXString
clang_constructUSR_ObjCCategory(const char *class_name,
const char *category_name);
/**
* \brief Construct a USR for a specified Objective-C protocol.
*/
CINDEX_LINKAGE CXString
clang_constructUSR_ObjCProtocol(const char *protocol_name);
/**
* \brief Construct a USR for a specified Objective-C instance variable and
* the USR for its containing class.
*/
CINDEX_LINKAGE CXString clang_constructUSR_ObjCIvar(const char *name,
CXString classUSR);
/**
* \brief Construct a USR for a specified Objective-C method and
* the USR for its containing class.
*/
CINDEX_LINKAGE CXString clang_constructUSR_ObjCMethod(const char *name,
unsigned isInstanceMethod,
CXString classUSR);
/**
* \brief Construct a USR for a specified Objective-C property and the USR
* for its containing class.
*/
CINDEX_LINKAGE CXString clang_constructUSR_ObjCProperty(const char *property,
CXString classUSR);
/**
* \brief Retrieve a name for the entity referenced by this cursor.
*/
@ -1157,22 +1198,22 @@ typedef enum CXTokenKind {
* \brief A token that contains some kind of punctuation.
*/
CXToken_Punctuation,
/**
* \brief A language keyword.
*/
CXToken_Keyword,
/**
* \brief An identifier (that is not a keyword).
*/
CXToken_Identifier,
/**
* \brief A numeric, string, or character literal.
*/
CXToken_Literal,
/**
* \brief A comment.
*/
@ -1191,7 +1232,7 @@ typedef struct {
* \brief Determine the kind of the given token.
*/
CINDEX_LINKAGE CXTokenKind clang_getTokenKind(CXToken);
/**
* \brief Determine the spelling of the given token.
*
@ -1199,13 +1240,13 @@ CINDEX_LINKAGE CXTokenKind clang_getTokenKind(CXToken);
* the text of an identifier or keyword.
*/
CINDEX_LINKAGE CXString clang_getTokenSpelling(CXTranslationUnit, CXToken);
/**
* \brief Retrieve the source location of the given token.
*/
CINDEX_LINKAGE CXSourceLocation clang_getTokenLocation(CXTranslationUnit,
CINDEX_LINKAGE CXSourceLocation clang_getTokenLocation(CXTranslationUnit,
CXToken);
/**
* \brief Retrieve a source range that covers the given token.
*/
@ -1230,7 +1271,7 @@ CINDEX_LINKAGE CXSourceRange clang_getTokenExtent(CXTranslationUnit, CXToken);
*/
CINDEX_LINKAGE void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
CXToken **Tokens, unsigned *NumTokens);
/**
* \brief Annotate the given set of tokens by providing cursors for each token
* that can be mapped to a specific entity within the abstract syntax tree.
@ -1264,17 +1305,17 @@ CINDEX_LINKAGE void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
CINDEX_LINKAGE void clang_annotateTokens(CXTranslationUnit TU,
CXToken *Tokens, unsigned NumTokens,
CXCursor *Cursors);
/**
* \brief Free the given set of tokens.
*/
CINDEX_LINKAGE void clang_disposeTokens(CXTranslationUnit TU,
CINDEX_LINKAGE void clang_disposeTokens(CXTranslationUnit TU,
CXToken *Tokens, unsigned NumTokens);
/**
* @}
*/
/**
* \defgroup CINDEX_DEBUG Debugging facilities
*
@ -1689,7 +1730,7 @@ void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results);
* \brief Determine the number of diagnostics produced prior to the
* location where code completion was performed.
*/
CINDEX_LINKAGE
CINDEX_LINKAGE
unsigned clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *Results);
/**
@ -1701,7 +1742,7 @@ unsigned clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *Results);
* \returns the requested diagnostic. This diagnostic must be freed
* via a call to \c clang_disposeDiagnostic().
*/
CINDEX_LINKAGE
CINDEX_LINKAGE
CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results,
unsigned Index);
@ -1726,10 +1767,10 @@ CINDEX_LINKAGE CXString clang_getClangVersion();
* \brief Return a version string, suitable for showing to a user, but not
* intended to be parsed (the format is not guaranteed to be stable).
*/
/**
* \brief Visitor invoked for each file in a translation unit
* \brief Visitor invoked for each file in a translation unit
* (used with clang_getInclusions()).
*
* This visitor function will be invoked by clang_getInclusions() for each

View File

@ -40,6 +40,7 @@ namespace clang {
class ASTRecordLayout;
class BlockExpr;
class CharUnits;
class Diagnostic;
class Expr;
class ExternalASTSource;
class IdentifierTable;
@ -950,8 +951,6 @@ class ASTContext {
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
void CollectNonClassIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
void CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
unsigned CountSynthesizedIvars(const ObjCInterfaceDecl *OI);
unsigned CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD);
void CollectInheritedProtocols(const Decl *CDecl,

View File

@ -319,7 +319,19 @@ class ValueDecl : public NamedDecl {
/// \brief Represents a ValueDecl that came out of a declarator.
/// Contains type source information through TypeSourceInfo.
class DeclaratorDecl : public ValueDecl {
TypeSourceInfo *DeclInfo;
// A struct representing both a TInfo and a syntactic qualifier,
// to be used for the (uncommon) case of out-of-line declarations.
struct ExtInfo {
TypeSourceInfo *TInfo;
NestedNameSpecifier *NNS;
SourceRange NNSRange;
};
llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo;
bool hasExtInfo() const { return DeclInfo.is<ExtInfo*>(); }
ExtInfo *getExtInfo() { return DeclInfo.get<ExtInfo*>(); }
const ExtInfo *getExtInfo() const { return DeclInfo.get<ExtInfo*>(); }
protected:
DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L,
@ -327,8 +339,29 @@ class DeclaratorDecl : public ValueDecl {
: ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {}
public:
TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; }
void setTypeSourceInfo(TypeSourceInfo *TInfo) { DeclInfo = TInfo; }
virtual ~DeclaratorDecl();
virtual void Destroy(ASTContext &C);
TypeSourceInfo *getTypeSourceInfo() const {
return hasExtInfo()
? DeclInfo.get<ExtInfo*>()->TInfo
: DeclInfo.get<TypeSourceInfo*>();
}
void setTypeSourceInfo(TypeSourceInfo *TI) {
if (hasExtInfo())
DeclInfo.get<ExtInfo*>()->TInfo = TI;
else
DeclInfo = TI;
}
NestedNameSpecifier *getQualifier() const {
return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNS : 0;
}
SourceRange getQualifierRange() const {
return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNSRange : SourceRange();
}
void setQualifierInfo(NestedNameSpecifier *Qualifier,
SourceRange QualifierRange);
SourceLocation getTypeSpecStartLoc() const;
@ -500,7 +533,8 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
bool isExternC() const;
/// isBlockVarDecl - Returns true for local variable declarations. Note that
/// this includes static variables inside of functions.
/// this includes static variables inside of functions. It also includes
/// variables inside blocks.
///
/// void foo() { int x; static int y; extern int z; }
///
@ -512,6 +546,17 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
return false;
}
/// isFunctionOrMethodVarDecl - Similar to isBlockVarDecl, but excludes
/// variables declared in blocks.
bool isFunctionOrMethodVarDecl() const {
if (getKind() != Decl::Var)
return false;
if (const DeclContext *DC = getDeclContext())
return DC->getLookupContext()->isFunctionOrMethod() &&
DC->getLookupContext()->getDeclKind() != Decl::Block;
return false;
}
/// \brief Determines whether this is a static data member.
///
/// This will only be true in C++, and applies to, e.g., the
@ -797,12 +842,14 @@ class ParmVarDecl : public VarDecl {
/// FIXME: Also can be paced into the bitfields in Decl.
/// in, inout, etc.
unsigned objcDeclQualifier : 6;
bool HasInheritedDefaultArg : 1;
protected:
ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
StorageClass S, Expr *DefArg)
: VarDecl(DK, DC, L, Id, T, TInfo, S), objcDeclQualifier(OBJC_TQ_None) {
: VarDecl(DK, DC, L, Id, T, TInfo, S),
objcDeclQualifier(OBJC_TQ_None), HasInheritedDefaultArg(false) {
setDefaultArg(DefArg);
}
@ -881,6 +928,14 @@ class ParmVarDecl : public VarDecl {
Init = (UnparsedDefaultArgument *)0;
}
bool hasInheritedDefaultArg() const {
return HasInheritedDefaultArg;
}
void setHasInheritedDefaultArg(bool I = true) {
HasInheritedDefaultArg = I;
}
QualType getOriginalType() const {
if (getTypeSourceInfo())
return getTypeSourceInfo()->getType();
@ -1512,22 +1567,38 @@ class TagDecl
/// IsEmbeddedInDeclarator - True if this tag declaration is
/// "embedded" (i.e., defined or declared for the very first time)
/// in the syntax of a declarator,
/// in the syntax of a declarator.
bool IsEmbeddedInDeclarator : 1;
/// TypedefForAnonDecl - If a TagDecl is anonymous and part of a typedef,
/// this points to the TypedefDecl. Used for mangling.
TypedefDecl *TypedefForAnonDecl;
SourceLocation TagKeywordLoc;
SourceLocation RBraceLoc;
// A struct representing syntactic qualifier info,
// to be used for the (uncommon) case of out-of-line declarations.
struct ExtInfo {
NestedNameSpecifier *NNS;
SourceRange NNSRange;
};
/// TypedefDeclOrQualifier - If the (out-of-line) tag declaration name
/// is qualified, it points to the qualifier info (nns and range);
/// otherwise, if the tag declaration is anonymous and it is part of
/// a typedef, it points to the TypedefDecl (used for mangling);
/// otherwise, it is a null (TypedefDecl) pointer.
llvm::PointerUnion<TypedefDecl*, ExtInfo*> TypedefDeclOrQualifier;
bool hasExtInfo() const { return TypedefDeclOrQualifier.is<ExtInfo*>(); }
ExtInfo *getExtInfo() { return TypedefDeclOrQualifier.get<ExtInfo*>(); }
const ExtInfo *getExtInfo() const {
return TypedefDeclOrQualifier.get<ExtInfo*>();
}
protected:
TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, TagDecl *PrevDecl,
SourceLocation TKL = SourceLocation())
: TypeDecl(DK, DC, L, Id), DeclContext(DK), TypedefForAnonDecl(0),
TagKeywordLoc(TKL) {
TagDecl(Kind DK, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
TagDecl *PrevDecl, SourceLocation TKL = SourceLocation())
: TypeDecl(DK, DC, L, Id), DeclContext(DK), TagKeywordLoc(TKL),
TypedefDeclOrQualifier((TypedefDecl*) 0) {
assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum");
TagDeclKind = TK;
IsDefinition = false;
@ -1539,6 +1610,8 @@ class TagDecl
virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
public:
void Destroy(ASTContext &C);
typedef redeclarable_base::redecl_iterator redecl_iterator;
redecl_iterator redecls_begin() const {
return redeclarable_base::redecls_begin();
@ -1618,8 +1691,21 @@ class TagDecl
bool isUnion() const { return getTagKind() == TK_union; }
bool isEnum() const { return getTagKind() == TK_enum; }
TypedefDecl *getTypedefForAnonDecl() const { return TypedefForAnonDecl; }
void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefForAnonDecl = TDD; }
TypedefDecl *getTypedefForAnonDecl() const {
return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>();
}
void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefDeclOrQualifier = TDD; }
NestedNameSpecifier *getQualifier() const {
return hasExtInfo() ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNS : 0;
}
SourceRange getQualifierRange() const {
return hasExtInfo()
? TypedefDeclOrQualifier.get<ExtInfo*>()->NNSRange
: SourceRange();
}
void setQualifierInfo(NestedNameSpecifier *Qualifier,
SourceRange QualifierRange);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }

View File

@ -660,7 +660,7 @@ class DeclContext {
/// \brief Determine whether this declaration context is equivalent
/// to the declaration context DC.
bool Equals(DeclContext *DC) {
return this->getPrimaryContext() == DC->getPrimaryContext();
return DC && this->getPrimaryContext() == DC->getPrimaryContext();
}
/// \brief Determine whether this declaration context encloses the

View File

@ -7,7 +7,8 @@
//
//===----------------------------------------------------------------------===//
//
// This file defines the C++ Decl subclasses.
// This file defines the C++ Decl subclasses, other than those for
// templates (in DeclTemplate.h) and friends (in DeclFriend.h).
//
//===----------------------------------------------------------------------===//
@ -32,6 +33,7 @@ class CXXDestructorDecl;
class CXXMethodDecl;
class CXXRecordDecl;
class CXXMemberLookupCriteria;
class FriendDecl;
/// \brief Represents any kind of function declaration, whether it is a
/// concrete function or a function template.
@ -298,6 +300,11 @@ class CXXRecordDecl : public RecordDecl {
/// Definition - The declaration which defines this record.
CXXRecordDecl *Definition;
/// FirstFriend - The first friend declaration in this class, or
/// null if there aren't any. This is actually currently stored
/// in reverse order.
FriendDecl *FirstFriend;
} *DefinitionData;
struct DefinitionData &data() {
@ -322,12 +329,6 @@ class CXXRecordDecl : public RecordDecl {
llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*>
TemplateOrInstantiation;
void getNestedVisibleConversionFunctions(CXXRecordDecl *RD,
const llvm::SmallPtrSet<CanQualType, 8> &TopConversionsTypeSet,
const llvm::SmallPtrSet<CanQualType, 8> &HiddenConversionTypes);
void collectConversionFunctions(
llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet) const;
protected:
CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
@ -458,6 +459,13 @@ class CXXRecordDecl : public RecordDecl {
return ctor_iterator(decls_end());
}
/// An iterator over friend declarations. All of these are defined
/// in DeclFriend.h.
class friend_iterator;
friend_iterator friend_begin() const;
friend_iterator friend_end() const;
void pushFriendDecl(FriendDecl *FD);
/// hasConstCopyConstructor - Determines whether this class has a
/// copy constructor that accepts a const-qualified argument.
bool hasConstCopyConstructor(ASTContext &Context) const;
@ -545,14 +553,6 @@ class CXXRecordDecl : public RecordDecl {
/// in current class; including conversion function templates.
const UnresolvedSetImpl *getVisibleConversionFunctions();
/// addVisibleConversionFunction - Add a new conversion function to the
/// list of visible conversion functions.
void addVisibleConversionFunction(CXXConversionDecl *ConvDecl);
/// \brief Add a new conversion function template to the list of visible
/// conversion functions.
void addVisibleConversionFunction(FunctionTemplateDecl *ConvDecl);
/// addConversionFunction - Add a new conversion function to the
/// list of conversion functions.
void addConversionFunction(CXXConversionDecl *ConvDecl);
@ -1385,77 +1385,6 @@ class CXXConversionDecl : public CXXMethodDecl {
static bool classofKind(Kind K) { return K == CXXConversion; }
};
/// FriendDecl - Represents the declaration of a friend entity,
/// which can be a function, a type, or a templated function or type.
// For example:
///
/// @code
/// template <typename T> class A {
/// friend int foo(T);
/// friend class B;
/// friend T; // only in C++0x
/// template <typename U> friend class C;
/// template <typename U> friend A& operator+=(A&, const U&) { ... }
/// };
/// @endcode
///
/// The semantic context of a friend decl is its declaring class.
class FriendDecl : public Decl {
public:
typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion;
private:
// The declaration that's a friend of this class.
FriendUnion Friend;
// Location of the 'friend' specifier.
SourceLocation FriendLoc;
// FIXME: Hack to keep track of whether this was a friend function
// template specialization.
bool WasSpecialization;
FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
SourceLocation FriendL)
: Decl(Decl::Friend, DC, L),
Friend(Friend),
FriendLoc(FriendL),
WasSpecialization(false) {
}
public:
static FriendDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, FriendUnion Friend_,
SourceLocation FriendL);
/// If this friend declaration names an (untemplated but
/// possibly dependent) type, return the type; otherwise
/// return null. This is used only for C++0x's unelaborated
/// friend type declarations.
Type *getFriendType() const {
return Friend.dyn_cast<Type*>();
}
/// If this friend declaration doesn't name an unelaborated
/// type, return the inner declaration.
NamedDecl *getFriendDecl() const {
return Friend.dyn_cast<NamedDecl*>();
}
/// Retrieves the location of the 'friend' keyword.
SourceLocation getFriendLoc() const {
return FriendLoc;
}
bool wasSpecialization() const { return WasSpecialization; }
void setSpecialization(bool WS) { WasSpecialization = WS; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const FriendDecl *D) { return true; }
static bool classofKind(Kind K) { return K == Decl::Friend; }
};
/// LinkageSpecDecl - This represents a linkage specification. For example:
/// extern "C" void foo();
///

View File

@ -0,0 +1,167 @@
//===-- DeclFriend.h - Classes for C++ friend declarations -*- C++ -*------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the section of the AST representing C++ friend
// declarations.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLFRIEND_H
#define LLVM_CLANG_AST_DECLFRIEND_H
#include "clang/AST/DeclCXX.h"
namespace clang {
/// FriendDecl - Represents the declaration of a friend entity,
/// which can be a function, a type, or a templated function or type.
// For example:
///
/// @code
/// template <typename T> class A {
/// friend int foo(T);
/// friend class B;
/// friend T; // only in C++0x
/// template <typename U> friend class C;
/// template <typename U> friend A& operator+=(A&, const U&) { ... }
/// };
/// @endcode
///
/// The semantic context of a friend decl is its declaring class.
class FriendDecl : public Decl {
public:
typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion;
private:
// The declaration that's a friend of this class.
FriendUnion Friend;
// A pointer to the next friend in the sequence.
FriendDecl *NextFriend;
// Location of the 'friend' specifier.
SourceLocation FriendLoc;
// FIXME: Hack to keep track of whether this was a friend function
// template specialization.
bool WasSpecialization;
friend class CXXRecordDecl::friend_iterator;
friend class CXXRecordDecl;
FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
SourceLocation FriendL)
: Decl(Decl::Friend, DC, L),
Friend(Friend),
NextFriend(0),
FriendLoc(FriendL),
WasSpecialization(false) {
}
public:
static FriendDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, FriendUnion Friend_,
SourceLocation FriendL);
/// If this friend declaration names an (untemplated but
/// possibly dependent) type, return the type; otherwise
/// return null. This is used only for C++0x's unelaborated
/// friend type declarations.
Type *getFriendType() const {
return Friend.dyn_cast<Type*>();
}
/// If this friend declaration doesn't name an unelaborated
/// type, return the inner declaration.
NamedDecl *getFriendDecl() const {
return Friend.dyn_cast<NamedDecl*>();
}
/// Retrieves the location of the 'friend' keyword.
SourceLocation getFriendLoc() const {
return FriendLoc;
}
bool wasSpecialization() const { return WasSpecialization; }
void setSpecialization(bool WS) { WasSpecialization = WS; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const FriendDecl *D) { return true; }
static bool classofKind(Kind K) { return K == Decl::Friend; }
};
/// An iterator over the friend declarations of a class.
class CXXRecordDecl::friend_iterator {
FriendDecl *Ptr;
friend class CXXRecordDecl;
explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {}
public:
friend_iterator() {}
typedef FriendDecl *value_type;
typedef FriendDecl *reference;
typedef FriendDecl *pointer;
typedef int difference_type;
typedef std::forward_iterator_tag iterator_category;
reference operator*() const { return Ptr; }
friend_iterator &operator++() {
assert(Ptr && "attempt to increment past end of friend list");
Ptr = Ptr->NextFriend;
return *this;
}
friend_iterator operator++(int) {
friend_iterator tmp = *this;
++*this;
return tmp;
}
bool operator==(const friend_iterator &Other) const {
return Ptr == Other.Ptr;
}
bool operator!=(const friend_iterator &Other) const {
return Ptr != Other.Ptr;
}
friend_iterator &operator+=(difference_type N) {
assert(N >= 0 && "cannot rewind a CXXRecordDecl::friend_iterator");
while (N--)
++*this;
return *this;
}
friend_iterator operator+(difference_type N) const {
friend_iterator tmp = *this;
tmp += N;
return tmp;
}
};
inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const {
return friend_iterator(data().FirstFriend);
}
inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
return friend_iterator(0);
}
inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
assert(FD->NextFriend == 0 && "friend already has next friend?");
FD->NextFriend = data().FirstFriend;
data().FirstFriend = FD;
}
}
#endif

View File

@ -381,8 +381,6 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
ObjCPropertyDecl *FindPropertyVisibleInPrimaryClass(
IdentifierInfo *PropertyId) const;
// Marks the end of the container.
SourceRange getAtEndRange() const {
@ -445,9 +443,6 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
/// Protocols referenced in interface header declaration
ObjCProtocolList ReferencedProtocols;
/// Instance variables in the interface. This list is completely redundant.
ObjCList<ObjCIvarDecl> IVars;
/// List of categories defined for this class.
/// FIXME: Why is this a linked list??
ObjCCategoryDecl *CategoryList;
@ -538,7 +533,10 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
}
ObjCCategoryDecl* getClassExtension() const;
ObjCPropertyDecl
*FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const;
/// isSuperClassOf - Return true if this class is the specified class or is a
/// super class of the specified interface class.
bool isSuperClassOf(const ObjCInterfaceDecl *I) const {
@ -1330,6 +1328,10 @@ class ObjCPropertyDecl : public NamedDecl {
return PropertyIvarDecl;
}
/// Lookup a property by name in the specified DeclContext.
static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC,
IdentifierInfo *propertyID);
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCPropertyDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCProperty; }

View File

@ -16,6 +16,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
namespace clang {

View File

@ -112,13 +112,14 @@ class ASTRecordLayout {
/// PrimaryBase - The primary base info for this record.
PrimaryBaseInfo PrimaryBase;
/// BaseOffsets - Contains a map from base classes to their offset.
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsets;
typedef llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsetsMapTy;
/// BaseOffsets - Contains a map from base classes to their offset.
BaseOffsetsMapTy BaseOffsets;
/// VBaseOffsets - Contains a map from vbase classes to their offset.
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
llvm::DenseMap<const CXXRecordDecl *, uint64_t> VBaseOffsets;
BaseOffsetsMapTy VBaseOffsets;
};
/// CXXInfo - If the record layout is for a C++ record, this will have
@ -133,15 +134,14 @@ class ASTRecordLayout {
unsigned fieldcount);
// Constructor for C++ records.
typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
ASTRecordLayout(ASTContext &Ctx,
uint64_t size, unsigned alignment, uint64_t datasize,
const uint64_t *fieldoffsets, unsigned fieldcount,
uint64_t nonvirtualsize, unsigned nonvirtualalign,
const PrimaryBaseInfo &PrimaryBase,
const std::pair<const CXXRecordDecl *, uint64_t> *bases,
unsigned numbases,
const std::pair<const CXXRecordDecl *, uint64_t> *vbases,
unsigned numvbases);
const BaseOffsetsMapTy& BaseOffsets,
const BaseOffsetsMapTy& VBaseOffsets);
~ASTRecordLayout() {}

View File

@ -286,7 +286,8 @@ class CFG {
/// constructed CFG belongs to the caller.
static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C,
bool AddEHEdges = false,
bool AddScopes = false);
bool AddScopes = false /* NOT FULLY IMPLEMENTED.
NOT READY FOR GENERAL USE. */);
/// createBlock - Create a new block in the CFG. The CFG owns the block;
/// the caller should not directly free it.

View File

@ -46,8 +46,8 @@
// U -> unsigned
//
// Types may be postfixed with the following modifiers:
// * -> pointer
// & -> reference
// * -> pointer (optionally followed by an address space number)
// & -> reference (optionally followed by an address space number)
// C -> const
// D -> volatile

View File

@ -287,6 +287,10 @@ BUILTIN(__builtin_ia32_roundpd, "V2dV2di", "")
BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fi", "")
BUILTIN(__builtin_ia32_dppd, "V2dV2dV2di", "")
BUILTIN(__builtin_ia32_movntdqa, "V2LLiV2LLi*", "")
BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_pcmpeqq, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16ci", "")
#undef BUILTIN

View File

@ -63,4 +63,12 @@ def err_target_unknown_cpu : Error<"unknown target CPU '%0'">;
def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
def err_target_invalid_feature : Error<"invalid target feature '%0'">;
// Source manager
def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal;
def err_file_size_changed : Error<
"size of file '%0' changed since it was first processed (from %1 to %2)">,
DefaultFatal;
def err_file_modified : Error<
"file '%0' modified since it was first processed">, DefaultFatal;
}

View File

@ -59,7 +59,7 @@ def : DiagGroup<"nested-externs">;
def : DiagGroup<"newline-eof">;
def LongLong : DiagGroup<"long-long">;
def MismatchedTags : DiagGroup<"mismatched-tags">;
def : DiagGroup<"missing-field-initializers">;
def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
def NonNull : DiagGroup<"nonnull">;
def : DiagGroup<"nonportable-cfstrings">;
def : DiagGroup<"non-virtual-dtor">;
@ -147,6 +147,7 @@ def Format2 : DiagGroup<"format=2",
[FormatNonLiteral, FormatSecurity, FormatY2K]>;
def Extra : DiagGroup<"extra", [
MissingFieldInitializers,
SemiBeforeMethodBody,
SignCompare,
UnusedParameter

View File

@ -183,6 +183,7 @@ def err_objc_no_attributes_on_category : Error<
def err_objc_missing_end : Error<"missing @end">;
def warn_objc_protocol_qualifier_missing_id : Warning<
"protocol qualifiers without 'id' is archaic">;
def err_objc_unknown_at : Error<"expected an Objective-C directive after '@'">;
def err_objc_illegal_visibility_spec : Error<
"illegal visibility specification">;

View File

@ -428,11 +428,39 @@ def err_deep_exception_specs_differ : Error<
// C++ access checking
def err_class_redeclared_with_different_access : Error<
"%0 redeclared with '%1' access">;
def err_access_private : Error<"%0 is a private member of %1">;
def err_access_ctor_private : Error<"calling a private constructor of %0">;
// Say something about the context for these?
def err_access_protected : Error<"%0 is a protected member of %1">;
def err_access_ctor_protected : Error<"calling a protected constructor of %0">;
def err_access :
Error<"%1 is a %select{private|protected}0 member of %3">,
NoSFINAE;
def err_access_ctor :
Error<"calling a %select{private|protected}0 constructor of class %2">,
NoSFINAE;
def err_access_dtor_base :
Error<"base class %0 has %select{private|protected}1 destructor">,
NoSFINAE;
def err_access_dtor_vbase :
Error<"inherited virtual base class %0 has "
"%select{private|protected}1 destructor">,
NoSFINAE;
def err_access_dtor_field :
Error<"field of type %1 has %select{private|protected}2 destructor">,
NoSFINAE;
def err_access_dtor_var :
Error<"variable of type %1 has %select{private|protected}2 destructor">,
NoSFINAE;
def err_access_assign_field :
Error<"field of type %1 has %select{private|protected}2 copy assignment"
" operator">,
NoSFINAE;
def err_access_assign_base :
Error<"base class %0 has %select{private|protected}1 copy assignment"
" operator">,
NoSFINAE;
def err_access_copy_field :
Error<"field of type %1 has %select{private|protected}2 copy constructor">,
NoSFINAE;
def err_access_copy_base :
Error<"base class %0 has %select{private|protected}1 copy constructor">,
NoSFINAE;
def note_previous_access_declaration : Note<
"previously declared '%1' here">;
def err_access_outside_class : Error<
@ -1251,7 +1279,7 @@ def err_not_class_template_specialization : Error<
def err_template_spec_needs_header : Error<
"template specialization requires 'template<>'">;
def err_template_spec_needs_template_parameters : Error<
"template specialization or definition requires a template parameter list"
"template specialization or definition requires a template parameter list "
"corresponding to the nested type %0">;
def err_template_param_list_matches_nontemplate : Error<
"template parameter list matching the non-templated nested type %0 should "
@ -1562,6 +1590,9 @@ def warn_excess_initializers_in_char_array_initializer : ExtWarn<
"excess elements in char array initializer">;
def warn_initializer_string_for_char_array_too_long : ExtWarn<
"initializer-string for char array is too long">;
def warn_missing_field_initializers : Warning<
"missing field '%0' initializer">,
InGroup<MissingFieldInitializers>, DefaultIgnore;
def warn_braces_around_scalar_init : Warning<
"braces around scalar initializer">;
def err_many_braces_around_scalar_init : Error<
@ -1854,6 +1885,12 @@ def warn_mixed_sign_comparison : Warning<
def warn_mixed_sign_conditional : Warning<
"operands of ? are integers of different signs: %0 and %1">,
InGroup<DiagGroup<"sign-compare">>, DefaultIgnore;
def warn_lunsigned_always_true_comparison : Warning<
"comparison of unsigned expression %0 is always %1">,
InGroup<DiagGroup<"sign-compare">>, DefaultIgnore;
def warn_runsigned_always_true_comparison : Warning<
"comparison of %0 unsigned expression is always %1">,
InGroup<DiagGroup<"sign-compare">>, DefaultIgnore;
def err_invalid_this_use : Error<
"invalid use of 'this' outside of a nonstatic member function">;

View File

@ -18,6 +18,7 @@
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/TokenKinds.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
@ -236,9 +237,7 @@ class IdentifierInfoLookup {
/// Unlike the version in IdentifierTable, this returns a pointer instead
/// of a reference. If the pointer is NULL then the IdentifierInfo cannot
/// be found.
//
// FIXME: Move to StringRef API.
virtual IdentifierInfo* get(const char *NameStart, const char *NameEnd) = 0;
virtual IdentifierInfo* get(llvm::StringRef Name) = 0;
};
/// \brief An abstract class used to resolve numerical identifier
@ -283,16 +282,16 @@ class IdentifierTable {
/// get - Return the identifier token info for the specified named identifier.
///
IdentifierInfo &get(const char *NameStart, const char *NameEnd) {
IdentifierInfo &get(llvm::StringRef Name) {
llvm::StringMapEntry<IdentifierInfo*> &Entry =
HashTable.GetOrCreateValue(NameStart, NameEnd);
HashTable.GetOrCreateValue(Name);
IdentifierInfo *II = Entry.getValue();
if (II) return *II;
// No entry; if we have an external lookup, look there first.
if (ExternalLookup) {
II = ExternalLookup->get(NameStart, NameEnd);
II = ExternalLookup->get(Name);
if (II) {
// Cache in the StringMap for subsequent lookups.
Entry.setValue(II);
@ -312,6 +311,14 @@ class IdentifierTable {
return *II;
}
IdentifierInfo &get(const char *NameStart, const char *NameEnd) {
return get(llvm::StringRef(NameStart, NameEnd-NameStart));
}
IdentifierInfo &get(const char *Name, size_t NameLen) {
return get(llvm::StringRef(Name, NameLen));
}
/// \brief Creates a new IdentifierInfo from the given string.
///
/// This is a lower-level version of get() that requires that this
@ -343,10 +350,6 @@ class IdentifierTable {
return CreateIdentifierInfo(Name.begin(), Name.end());
}
IdentifierInfo &get(llvm::StringRef Name) {
return get(Name.begin(), Name.end());
}
typedef HashTableTy::const_iterator iterator;
typedef HashTableTy::const_iterator const_iterator;
@ -474,9 +477,7 @@ class SelectorTable {
SelectorName = "set";
SelectorName += Name->getName();
SelectorName[3] = toupper(SelectorName[3]);
IdentifierInfo *SetterName =
&Idents.get(SelectorName.data(),
SelectorName.data() + SelectorName.size());
IdentifierInfo *SetterName = &Idents.get(SelectorName);
return SelTable.getUnarySelector(SetterName);
}
};
@ -533,7 +534,7 @@ struct DenseMapInfo<clang::Selector> {
return LHS == RHS;
}
};
template <>
struct isPodLike<clang::Selector> { static const bool value = true; };

View File

@ -44,6 +44,7 @@ class LangOptions {
unsigned PascalStrings : 1; // Allow Pascal strings
unsigned WritableStrings : 1; // Allow writable strings
unsigned ConstStrings : 1; // Add const qualifier to strings (-Wwrite-strings)
unsigned LaxVectorConversions : 1;
unsigned AltiVec : 1; // Support AltiVec-style vector initializers.
unsigned Exceptions : 1; // Support exception handling.
@ -129,7 +130,7 @@ class LangOptions {
HexFloats = 0;
GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0;
C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0;
CXXOperatorNames = PascalStrings = WritableStrings = 0;
CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0;
Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0;
NeXTRuntime = 1;
RTTI = 1;

View File

@ -69,6 +69,10 @@ class PartialDiagnostic {
CodeModificationHint CodeModificationHints[MaxCodeModificationHints];
};
// NOTE: Sema assumes that PartialDiagnostic is location-invariant
// in the sense that its bits can be safely memcpy'ed and destructed
// in the new location.
/// DiagID - The diagnostic ID.
mutable unsigned DiagID;

View File

@ -20,6 +20,7 @@
namespace llvm {
class MemoryBuffer;
class raw_ostream;
class StringRef;
template <typename T> struct DenseMapInfo;
template <typename T> struct isPodLike;
}
@ -209,9 +210,9 @@ class FullSourceLoc : public SourceLocation {
const llvm::MemoryBuffer* getBuffer() const;
/// getBufferData - Return a pointer to the start and end of the source buffer
/// data for the specified FileID.
std::pair<const char*, const char*> getBufferData() const;
/// getBufferData - Return a StringRef to the source buffer data for the
/// specified FileID.
llvm::StringRef getBufferData() const;
/// getDecomposedLoc - Decompose the specified location into a raw FileID +
/// Offset pair. The first element is the FileID, the second is the

View File

@ -17,22 +17,24 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/Support/Allocator.h"
#include "llvm/System/DataTypes.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/DenseMap.h"
#include <vector>
#include <cassert>
namespace llvm {
class MemoryBuffer;
class StringRef;
}
namespace clang {
class Diagnostic;
class SourceManager;
class FileManager;
class FileEntry;
class IdentifierTokenInfo;
class LineTableInfo;
/// SrcMgr - Public enums and private classes that are part of the
/// SourceManager implementation.
///
@ -69,10 +71,14 @@ namespace SrcMgr {
/// if SourceLineCache is non-null.
unsigned NumLines;
/// getBuffer - Returns the memory buffer for the associated content. If
/// there is an error opening this buffer the first time, this manufactures
/// a temporary buffer and returns a non-empty error string.
const llvm::MemoryBuffer *getBuffer(std::string *ErrorStr = 0) const;
/// getBuffer - Returns the memory buffer for the associated content.
///
/// \param Diag Object through which diagnostics will be emitted it the
/// buffer cannot be retrieved.
///
/// \param Invalid If non-NULL, will be set \c true if an error occurred.
const llvm::MemoryBuffer *getBuffer(Diagnostic &Diag,
bool *Invalid = 0) const;
/// getSize - Returns the size of the content encapsulated by this
/// ContentCache. This can be the size of the source file or the size of an
@ -277,6 +283,9 @@ class ExternalSLocEntrySource {
/// location indicates where the expanded token came from and the instantiation
/// location specifies where it was expanded.
class SourceManager {
/// \brief Diagnostic object.
Diagnostic &Diag;
mutable llvm::BumpPtrAllocator ContentCacheAlloc;
/// FileInfos - Memoized information about all of the files tracked by this
@ -336,8 +345,8 @@ class SourceManager {
explicit SourceManager(const SourceManager&);
void operator=(const SourceManager&);
public:
SourceManager()
: ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
SourceManager(Diagnostic &Diag)
: Diag(Diag), ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
NumBinaryProbes(0) {
clearIDTables();
}
@ -408,7 +417,11 @@ class SourceManager {
unsigned Offset = 0);
/// \brief Retrieve the memory buffer associated with the given file.
const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File);
///
/// \param Invalid If non-NULL, will be set \c true if an error
/// occurs while retrieving the memory buffer.
const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File,
bool *Invalid = 0);
/// \brief Override the contents of the given source file by providing an
/// already-allocated buffer.
@ -429,8 +442,9 @@ class SourceManager {
/// getBuffer - Return the buffer for the specified FileID. If there is an
/// error opening this buffer the first time, this manufactures a temporary
/// buffer and returns a non-empty error string.
const llvm::MemoryBuffer *getBuffer(FileID FID, std::string *Error = 0) const{
return getSLocEntry(FID).getFile().getContentCache()->getBuffer(Error);
const llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = 0) const {
return getSLocEntry(FID).getFile().getContentCache()->getBuffer(Diag,
Invalid);
}
/// getFileEntryForID - Returns the FileEntry record for the provided FileID.
@ -438,9 +452,12 @@ class SourceManager {
return getSLocEntry(FID).getFile().getContentCache()->Entry;
}
/// getBufferData - Return a pointer to the start and end of the source buffer
/// data for the specified FileID.
std::pair<const char*, const char*> getBufferData(FileID FID) const;
/// getBufferData - Return a StringRef to the source buffer data for the
/// specified FileID.
///
/// \param FID The file ID whose contents will be returned.
/// \param Invalid If non-NULL, will be set true if an error occurred.
llvm::StringRef getBufferData(FileID FID, bool *Invalid = 0) const;
//===--------------------------------------------------------------------===//
@ -558,31 +575,37 @@ class SourceManager {
/// getCharacterData - Return a pointer to the start of the specified location
/// in the appropriate spelling MemoryBuffer.
const char *getCharacterData(SourceLocation SL) const;
///
/// \param Invalid If non-NULL, will be set \c true if an error occurs.
const char *getCharacterData(SourceLocation SL, bool *Invalid = 0) const;
/// getColumnNumber - Return the column # for the specified file position.
/// This is significantly cheaper to compute than the line number. This
/// returns zero if the column number isn't known. This may only be called on
/// a file sloc, so you must choose a spelling or instantiation location
/// before calling this method.
unsigned getColumnNumber(FileID FID, unsigned FilePos) const;
unsigned getSpellingColumnNumber(SourceLocation Loc) const;
unsigned getInstantiationColumnNumber(SourceLocation Loc) const;
unsigned getColumnNumber(FileID FID, unsigned FilePos,
bool *Invalid = 0) const;
unsigned getSpellingColumnNumber(SourceLocation Loc,
bool *Invalid = 0) const;
unsigned getInstantiationColumnNumber(SourceLocation Loc,
bool *Invalid = 0) const;
/// getLineNumber - Given a SourceLocation, return the spelling line number
/// for the position indicated. This requires building and caching a table of
/// line offsets for the MemoryBuffer, so this is not cheap: use only when
/// about to emit a diagnostic.
unsigned getLineNumber(FileID FID, unsigned FilePos) const;
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = 0) const;
unsigned getInstantiationLineNumber(SourceLocation Loc) const;
unsigned getSpellingLineNumber(SourceLocation Loc) const;
unsigned getInstantiationLineNumber(SourceLocation Loc,
bool *Invalid = 0) const;
unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
/// Return the filename or buffer identifier of the buffer the location is in.
/// Note that this name does not respect #line directives. Use getPresumedLoc
/// for normal clients.
const char *getBufferName(SourceLocation Loc) const;
const char *getBufferName(SourceLocation Loc, bool *Invalid = 0) const;
/// getFileCharacteristic - return the file characteristic of the specified
/// source location, indicating whether this is a normal file, a system
@ -678,7 +701,7 @@ class SourceManager {
void PrintStats() const;
unsigned sloc_entry_size() const { return SLocEntryTable.size(); }
// FIXME: Exposing this is a little gross; what we want is a good way
// to iterate the entries that were not defined in a PCH file (or
// any other external source).
@ -692,8 +715,8 @@ class SourceManager {
ExternalSLocEntries->ReadSLocEntry(ID);
return SLocEntryTable[ID];
}
const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const {
const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const {
return getSLocEntry(FID.ID);
}

View File

@ -347,7 +347,10 @@ class GRExprEngine : public GRSubEngine {
void VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst);
void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// Create a C++ temporary object for an rvalue.
void CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst);

View File

@ -66,17 +66,23 @@ class Action {
ActionList Inputs;
unsigned OwnsInputs : 1;
protected:
Action(ActionClass _Kind, types::ID _Type) : Kind(_Kind), Type(_Type) {}
Action(ActionClass _Kind, types::ID _Type)
: Kind(_Kind), Type(_Type), OwnsInputs(true) {}
Action(ActionClass _Kind, Action *Input, types::ID _Type)
: Kind(_Kind), Type(_Type), Inputs(&Input, &Input + 1) {}
: Kind(_Kind), Type(_Type), Inputs(&Input, &Input + 1), OwnsInputs(true) {}
Action(ActionClass _Kind, const ActionList &_Inputs, types::ID _Type)
: Kind(_Kind), Type(_Type), Inputs(_Inputs) {}
: Kind(_Kind), Type(_Type), Inputs(_Inputs), OwnsInputs(true) {}
public:
virtual ~Action();
const char *getClassName() const { return Action::getClassName(getKind()); }
bool getOwnsInputs() { return OwnsInputs; }
void setOwnsInputs(bool Value) { OwnsInputs = Value; }
ActionClass getKind() const { return Kind; }
types::ID getType() const { return Type; }

View File

@ -287,7 +287,7 @@ namespace driver {
arglist_type ActualArgs;
/// The list of arguments we synthesized.
arglist_type SynthesizedArgs;
mutable arglist_type SynthesizedArgs;
/// Is this only a proxy for the base ArgList?
bool OnlyProxy;

View File

@ -197,6 +197,8 @@ def fcolor_diagnostics : Flag<"-fcolor-diagnostics">,
HelpText<"Use colors in diagnostics">;
def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">,
HelpText<"Silence ObjC rewriting warnings">;
def Wwrite_strings : Flag<"-Wwrite-strings">,
HelpText<"Add const qualifier to string literals">;
def verify : Flag<"-verify">,
HelpText<"Verify emitted diagnostics and warnings">;

View File

@ -100,7 +100,9 @@ class PipedJob : public Job {
public:
PipedJob();
virtual ~PipedJob();
/// Add a command to the piped job (taking ownership).
void addCommand(Command *C) { Commands.push_back(C); }
const list_type &getCommands() const { return Commands; }
@ -130,7 +132,9 @@ class JobList : public Job {
public:
JobList();
virtual ~JobList();
/// Add a job to the list (taking ownership).
void addJob(Job *J) { Jobs.push_back(J); }
const list_type &getJobs() const { return Jobs; }

View File

@ -121,7 +121,7 @@ class ASTUnit {
};
friend class ConcurrencyCheck;
ASTUnit(bool MainFileIsAST);
ASTUnit(Diagnostic &Diag, bool MainFileIsAST);
~ASTUnit();
bool isMainFileAST() const { return MainFileIsAST; }

View File

@ -115,7 +115,7 @@ class PTHManager : public IdentifierInfoLookup {
/// Unlike the version in IdentifierTable, this returns a pointer instead
/// of a reference. If the pointer is NULL then the IdentifierInfo cannot
/// be found.
IdentifierInfo *get(const char *NameStart, const char *NameEnd);
IdentifierInfo *get(llvm::StringRef Name);
/// Create - This method creates PTHManager objects. The 'file' argument
/// is the name of the PTH file. This method returns NULL upon failure.

View File

@ -547,7 +547,9 @@ class Preprocessor {
/// after trigraph expansion and escaped-newline folding. In particular, this
/// wants to get the true, uncanonicalized, spelling of things like digraphs
/// UCNs, etc.
std::string getSpelling(const Token &Tok) const;
///
/// \param Invalid If non-NULL, will be set \c true if an error occurs.
std::string getSpelling(const Token &Tok, bool *Invalid = 0) const;
/// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a
/// token is the characters used to represent the token in the source file
@ -556,7 +558,8 @@ class Preprocessor {
/// UCNs, etc.
static std::string getSpelling(const Token &Tok,
const SourceManager &SourceMgr,
const LangOptions &Features);
const LangOptions &Features,
bool *Invalid = 0);
/// getSpelling - This method is used to get the spelling of a token into a
/// preallocated buffer, instead of as an std::string. The caller is required
@ -568,17 +571,20 @@ class Preprocessor {
/// to point to a constant buffer with the data already in it (avoiding a
/// copy). The caller is not allowed to modify the returned buffer pointer
/// if an internal buffer is returned.
unsigned getSpelling(const Token &Tok, const char *&Buffer) const;
unsigned getSpelling(const Token &Tok, const char *&Buffer,
bool *Invalid = 0) const;
/// getSpelling - This method is used to get the spelling of a token into a
/// SmallVector. Note that the returned StringRef may not point to the
/// supplied buffer if a copy can be avoided.
llvm::StringRef getSpelling(const Token &Tok,
llvm::SmallVectorImpl<char> &Buffer) const;
llvm::SmallVectorImpl<char> &Buffer,
bool *Invalid = 0) const;
/// getSpellingOfSingleCharacterNumericConstant - Tok is a numeric constant
/// with length 1, return the character.
char getSpellingOfSingleCharacterNumericConstant(const Token &Tok) const {
char getSpellingOfSingleCharacterNumericConstant(const Token &Tok,
bool *Invalid = 0) const {
assert(Tok.is(tok::numeric_constant) &&
Tok.getLength() == 1 && "Called on unsupported token");
assert(!Tok.needsCleaning() && "Token can't need cleaning with length 1");
@ -730,7 +736,7 @@ class Preprocessor {
/// This code concatenates and consumes tokens up to the '>' token. It returns
/// false if the > was found, otherwise it returns true if it finds and consumes
/// the EOM marker.
bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer);
bool ConcatenateIncludeName(llvm::SmallString<128> &FilenameBuffer);
private:

View File

@ -423,10 +423,15 @@ namespace {
/// (which requires a < after the Doxygen-comment delimiter). Otherwise,
/// we only return true when we find a non-member comment.
static bool
isDoxygenComment(SourceManager &SourceMgr, SourceRange Comment,
isDoxygenComment(SourceManager &SourceMgr, SourceRange Comment,
bool Member = false) {
bool Invalid = false;
const char *BufferStart
= SourceMgr.getBufferData(SourceMgr.getFileID(Comment.getBegin())).first;
= SourceMgr.getBufferData(SourceMgr.getFileID(Comment.getBegin()),
&Invalid).data();
if (Invalid)
return false;
const char *Start = BufferStart + SourceMgr.getFileOffset(Comment.getBegin());
const char* End = BufferStart + SourceMgr.getFileOffset(Comment.getEnd());
@ -488,9 +493,12 @@ const char *ASTContext::getCommentForDecl(const Decl *D) {
// beginning of the file buffer.
std::pair<FileID, unsigned> DeclStartDecomp
= SourceMgr.getDecomposedLoc(DeclStartLoc);
bool Invalid = false;
const char *FileBufferStart
= SourceMgr.getBufferData(DeclStartDecomp.first).first;
= SourceMgr.getBufferData(DeclStartDecomp.first, &Invalid).data();
if (Invalid)
return 0;
// First check whether we have a comment for a member.
if (LastComment != Comments.end() &&
!isa<TagDecl>(D) && !isa<NamespaceDecl>(D) &&
@ -971,22 +979,10 @@ void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
CollectNonClassIvars(OI, Ivars);
}
void ASTContext::CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(),
E = PD->prop_end(); I != E; ++I)
if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl())
Ivars.push_back(Ivar);
// Also look into nested protocols.
for (ObjCProtocolDecl::protocol_iterator P = PD->protocol_begin(),
E = PD->protocol_end(); P != E; ++P)
CollectProtocolSynthesizedIvars(*P, Ivars);
}
/// CollectNonClassIvars -
/// This routine collects all other ivars which are not declared in the class.
/// This includes synthesized ivars and those in class's implementation.
/// This includes synthesized ivars (via @synthesize) and those in
// class's @implementation.
///
void ASTContext::CollectNonClassIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
@ -997,21 +993,9 @@ void ASTContext::CollectNonClassIvars(const ObjCInterfaceDecl *OI,
Ivars.push_back(*I);
}
}
for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(),
E = OI->prop_end(); I != E; ++I) {
if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl())
Ivars.push_back(Ivar);
}
// Also look into interface's protocol list for properties declared
// in the protocol and whose ivars are synthesized.
for (ObjCInterfaceDecl::protocol_iterator P = OI->protocol_begin(),
PE = OI->protocol_end(); P != PE; ++P) {
ObjCProtocolDecl *PD = (*P);
CollectProtocolSynthesizedIvars(PD, Ivars);
}
// Also add any ivar defined in this class's implementation
// Also add any ivar defined in this class's implementation. This
// includes synthesized ivars.
if (ObjCImplementationDecl *ImplDecl = OI->getImplementation()) {
for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
E = ImplDecl->ivar_end(); I != E; ++I)
@ -4760,7 +4744,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
return QualType();
case Type::Vector:
// FIXME: The merged type should be an ExtVector!
if (areCompatVectorTypes(LHS->getAs<VectorType>(), RHS->getAs<VectorType>()))
if (areCompatVectorTypes(LHSCan->getAs<VectorType>(),
RHSCan->getAs<VectorType>()))
return LHS;
return QualType();
case Type::ObjCInterface: {
@ -4997,13 +4982,24 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context,
Done = false;
while (!Done) {
switch (*Str++) {
switch (char c = *Str++) {
default: Done = true; --Str; break;
case '*':
Type = Context.getPointerType(Type);
break;
case '&':
Type = Context.getLValueReferenceType(Type);
{
// Both pointers and references can have their pointee types
// qualified with an address space.
char *End;
unsigned AddrSpace = strtoul(Str, &End, 10);
if (End != Str && AddrSpace != 0) {
Type = Context.getAddrSpaceQualType(Type, AddrSpace);
Str = End;
}
}
if (c == '*')
Type = Context.getPointerType(Type);
else
Type = Context.getLValueReferenceType(Type);
break;
// FIXME: There's no way to have a built-in with an rvalue ref arg.
case 'C':

View File

@ -1592,6 +1592,12 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
Name.getAsIdentifierInfo(),
Importer.Import(D->getTagKeywordLoc()),
0);
// Import the qualifier, if any.
if (D->getQualifier()) {
NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
SourceRange NNSRange = Importer.Import(D->getQualifierRange());
D2->setQualifierInfo(NNS, NNSRange);
}
D2->setAccess(D->getAccess());
D2->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, D2);
@ -1734,6 +1740,12 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
Name.getAsIdentifierInfo(),
Importer.Import(D->getTagKeywordLoc()));
}
// Import the qualifier, if any.
if (D->getQualifier()) {
NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
SourceRange NNSRange = Importer.Import(D->getQualifierRange());
D2->setQualifierInfo(NNS, NNSRange);
}
D2->setLexicalDeclContext(LexicalDC);
LexicalDC->addDecl(D2);
}
@ -1900,6 +1912,13 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
D->isInlineSpecified(),
D->hasWrittenPrototype());
}
// Import the qualifier, if any.
if (D->getQualifier()) {
NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
SourceRange NNSRange = Importer.Import(D->getQualifierRange());
ToFunction->setQualifierInfo(NNS, NNSRange);
}
ToFunction->setAccess(D->getAccess());
ToFunction->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToFunction);
@ -2110,6 +2129,12 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC, Loc,
Name.getAsIdentifierInfo(), T, TInfo,
D->getStorageClass());
// Import the qualifier, if any.
if (D->getQualifier()) {
NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
SourceRange NNSRange = Importer.Import(D->getQualifierRange());
ToVar->setQualifierInfo(NNS, NNSRange);
}
ToVar->setAccess(D->getAccess());
ToVar->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToVar);
@ -2176,6 +2201,7 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
Loc, Name.getAsIdentifierInfo(),
T, TInfo, D->getStorageClass(),
/*FIXME: Default argument*/ 0);
ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg());
return Importer.Imported(D, ToParm);
}
@ -3063,7 +3089,7 @@ FileID ASTImporter::Import(FileID FromID) {
FromSLoc.getFile().getFileCharacteristic());
} else {
// FIXME: We want to re-use the existing MemoryBuffer!
const llvm::MemoryBuffer *FromBuf = Cache->getBuffer();
const llvm::MemoryBuffer *FromBuf = Cache->getBuffer(getDiags());
llvm::MemoryBuffer *ToBuf
= llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBufferStart(),
FromBuf->getBufferEnd(),

View File

@ -11,6 +11,7 @@ add_clang_library(clangAST
Decl.cpp
DeclBase.cpp
DeclCXX.cpp
DeclFriend.cpp
DeclGroup.cpp
DeclObjC.cpp
DeclPrinter.cpp

View File

@ -495,9 +495,16 @@ NamedDecl *NamedDecl::getUnderlyingDecl() {
// DeclaratorDecl Implementation
//===----------------------------------------------------------------------===//
DeclaratorDecl::~DeclaratorDecl() {}
void DeclaratorDecl::Destroy(ASTContext &C) {
if (hasExtInfo())
C.Deallocate(getExtInfo());
ValueDecl::Destroy(C);
}
SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
if (DeclInfo) {
TypeLoc TL = DeclInfo->getTypeLoc();
TypeLoc TL = getTypeSourceInfo()->getTypeLoc();
while (true) {
TypeLoc NextTL = TL.getNextTypeLoc();
if (!NextTL)
@ -508,6 +515,36 @@ SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
return SourceLocation();
}
void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
SourceRange QualifierRange) {
if (Qualifier) {
// Make sure the extended decl info is allocated.
if (!hasExtInfo()) {
// Save (non-extended) type source info pointer.
TypeSourceInfo *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
// Allocate external info struct.
DeclInfo = new (getASTContext()) ExtInfo;
// Restore savedTInfo into (extended) decl info.
getExtInfo()->TInfo = savedTInfo;
}
// Set qualifier info.
getExtInfo()->NNS = Qualifier;
getExtInfo()->NNSRange = QualifierRange;
}
else {
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
assert(QualifierRange.isInvalid());
if (hasExtInfo()) {
// Save type source info pointer.
TypeSourceInfo *savedTInfo = getExtInfo()->TInfo;
// Deallocate the extended decl info.
getASTContext().Deallocate(getExtInfo());
// Restore savedTInfo into (non-extended) decl info.
DeclInfo = savedTInfo;
}
}
}
//===----------------------------------------------------------------------===//
// VarDecl Implementation
//===----------------------------------------------------------------------===//
@ -542,7 +579,7 @@ void VarDecl::Destroy(ASTContext& C) {
}
}
this->~VarDecl();
C.Deallocate((void *)this);
DeclaratorDecl::Destroy(C);
}
VarDecl::~VarDecl() {
@ -818,7 +855,7 @@ void FunctionDecl::Destroy(ASTContext& C) {
C.Deallocate(ParamInfo);
Decl::Destroy(C);
DeclaratorDecl::Destroy(C);
}
void FunctionDecl::getNameForDiagnostic(std::string &S,
@ -1348,6 +1385,12 @@ bool FieldDecl::isAnonymousStructOrUnion() const {
// TagDecl Implementation
//===----------------------------------------------------------------------===//
void TagDecl::Destroy(ASTContext &C) {
if (hasExtInfo())
C.Deallocate(getExtInfo());
TypeDecl::Destroy(C);
}
SourceRange TagDecl::getSourceRange() const {
SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation();
return SourceRange(TagKeywordLoc, E);
@ -1409,6 +1452,26 @@ TagDecl::TagKind TagDecl::getTagKindForTypeSpec(unsigned TypeSpec) {
}
}
void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
SourceRange QualifierRange) {
if (Qualifier) {
// Make sure the extended qualifier info is allocated.
if (!hasExtInfo())
TypedefDeclOrQualifier = new (getASTContext()) ExtInfo;
// Set qualifier info.
getExtInfo()->NNS = Qualifier;
getExtInfo()->NNSRange = QualifierRange;
}
else {
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
assert(QualifierRange.isInvalid());
if (hasExtInfo()) {
getASTContext().Deallocate(getExtInfo());
TypedefDeclOrQualifier = (TypedefDecl*) 0;
}
}
}
//===----------------------------------------------------------------------===//
// EnumDecl Implementation
//===----------------------------------------------------------------------===//
@ -1422,7 +1485,7 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
}
void EnumDecl::Destroy(ASTContext& C) {
Decl::Destroy(C);
TagDecl::Destroy(C);
}
void EnumDecl::completeDefinition(QualType NewType,
@ -1529,7 +1592,7 @@ void NamespaceDecl::Destroy(ASTContext& C) {
// together. They are all top-level Decls.
this->~NamespaceDecl();
C.Deallocate((void *)this);
Decl::Destroy(C);
}
@ -1563,7 +1626,7 @@ EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
void EnumConstantDecl::Destroy(ASTContext& C) {
if (Init) Init->Destroy(C);
Decl::Destroy(C);
ValueDecl::Destroy(C);
}
TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,

View File

@ -15,6 +15,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExternalASTSource.h"

View File

@ -33,7 +33,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialDestructor(true), ComputedVisibleConversions(false),
Bases(0), NumBases(0), VBases(0), NumVBases(0),
Definition(D) {
Definition(D), FirstFriend(0) {
}
CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
@ -318,105 +318,128 @@ void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
data().PlainOldData = false;
}
void
CXXRecordDecl::collectConversionFunctions(
llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet) const
{
const UnresolvedSetImpl *Cs = getConversionFunctions();
for (UnresolvedSetImpl::iterator I = Cs->begin(), E = Cs->end();
I != E; ++I) {
NamedDecl *TopConv = *I;
CanQualType TConvType;
if (FunctionTemplateDecl *TConversionTemplate =
dyn_cast<FunctionTemplateDecl>(TopConv))
TConvType =
getASTContext().getCanonicalType(
TConversionTemplate->getTemplatedDecl()->getResultType());
else
TConvType =
getASTContext().getCanonicalType(
cast<CXXConversionDecl>(TopConv)->getConversionType());
ConversionsTypeSet.insert(TConvType);
}
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
QualType T;
if (FunctionTemplateDecl *ConvTemp = dyn_cast<FunctionTemplateDecl>(Conv))
T = ConvTemp->getTemplatedDecl()->getResultType();
else
T = cast<CXXConversionDecl>(Conv)->getConversionType();
return Context.getCanonicalType(T);
}
/// getNestedVisibleConversionFunctions - imports unique conversion
/// functions from base classes into the visible conversion function
/// list of the class 'RD'. This is a private helper method.
/// TopConversionsTypeSet is the set of conversion functions of the class
/// we are interested in. HiddenConversionTypes is set of conversion functions
/// of the immediate derived class which hides the conversion functions found
/// in current class.
void
CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD,
const llvm::SmallPtrSet<CanQualType, 8> &TopConversionsTypeSet,
const llvm::SmallPtrSet<CanQualType, 8> &HiddenConversionTypes)
{
bool inTopClass = (RD == this);
QualType ClassType = getASTContext().getTypeDeclType(this);
if (const RecordType *Record = ClassType->getAs<RecordType>()) {
const UnresolvedSetImpl *Cs
= cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
for (UnresolvedSetImpl::iterator I = Cs->begin(), E = Cs->end();
I != E; ++I) {
NamedDecl *Conv = *I;
// Only those conversions not exact match of conversions in current
// class are candidateconversion routines.
CanQualType ConvType;
if (FunctionTemplateDecl *ConversionTemplate =
dyn_cast<FunctionTemplateDecl>(Conv))
ConvType =
getASTContext().getCanonicalType(
ConversionTemplate->getTemplatedDecl()->getResultType());
else
ConvType =
getASTContext().getCanonicalType(
cast<CXXConversionDecl>(Conv)->getConversionType());
// We only add conversion functions found in the base class if they
// are not hidden by those found in HiddenConversionTypes which are
// the conversion functions in its derived class.
if (inTopClass ||
(!TopConversionsTypeSet.count(ConvType) &&
!HiddenConversionTypes.count(ConvType)) ) {
if (FunctionTemplateDecl *ConversionTemplate =
dyn_cast<FunctionTemplateDecl>(Conv))
RD->addVisibleConversionFunction(ConversionTemplate);
/// Collect the visible conversions of a base class.
///
/// \param Base a base class of the class we're considering
/// \param InVirtual whether this base class is a virtual base (or a base
/// of a virtual base)
/// \param Access the access along the inheritance path to this base
/// \param ParentHiddenTypes the conversions provided by the inheritors
/// of this base
/// \param Output the set to which to add conversions from non-virtual bases
/// \param VOutput the set to which to add conversions from virtual bases
/// \param HiddenVBaseCs the set of conversions which were hidden in a
/// virtual base along some inheritance path
static void CollectVisibleConversions(ASTContext &Context,
CXXRecordDecl *Record,
bool InVirtual,
AccessSpecifier Access,
const llvm::SmallPtrSet<CanQualType, 8> &ParentHiddenTypes,
UnresolvedSetImpl &Output,
UnresolvedSetImpl &VOutput,
llvm::SmallPtrSet<NamedDecl*, 8> &HiddenVBaseCs) {
// The set of types which have conversions in this class or its
// subclasses. As an optimization, we don't copy the derived set
// unless it might change.
const llvm::SmallPtrSet<CanQualType, 8> *HiddenTypes = &ParentHiddenTypes;
llvm::SmallPtrSet<CanQualType, 8> HiddenTypesBuffer;
// Collect the direct conversions and figure out which conversions
// will be hidden in the subclasses.
UnresolvedSetImpl &Cs = *Record->getConversionFunctions();
if (!Cs.empty()) {
HiddenTypesBuffer = ParentHiddenTypes;
HiddenTypes = &HiddenTypesBuffer;
for (UnresolvedSetIterator I = Cs.begin(), E = Cs.end(); I != E; ++I) {
bool Hidden =
!HiddenTypesBuffer.insert(GetConversionType(Context, I.getDecl()));
// If this conversion is hidden and we're in a virtual base,
// remember that it's hidden along some inheritance path.
if (Hidden && InVirtual)
HiddenVBaseCs.insert(cast<NamedDecl>(I.getDecl()->getCanonicalDecl()));
// If this conversion isn't hidden, add it to the appropriate output.
else if (!Hidden) {
AccessSpecifier IAccess
= CXXRecordDecl::MergeAccess(Access, I.getAccess());
if (InVirtual)
VOutput.addDecl(I.getDecl(), IAccess);
else
RD->addVisibleConversionFunction(cast<CXXConversionDecl>(Conv));
Output.addDecl(I.getDecl(), IAccess);
}
}
}
if (getNumBases() == 0 && getNumVBases() == 0)
return;
// Collect information recursively from any base classes.
for (CXXRecordDecl::base_class_iterator
I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) {
const RecordType *RT = I->getType()->getAs<RecordType>();
if (!RT) continue;
llvm::SmallPtrSet<CanQualType, 8> ConversionFunctions;
if (!inTopClass)
collectConversionFunctions(ConversionFunctions);
AccessSpecifier BaseAccess
= CXXRecordDecl::MergeAccess(Access, I->getAccessSpecifier());
bool BaseInVirtual = InVirtual || I->isVirtual();
for (CXXRecordDecl::base_class_iterator VBase = vbases_begin(),
E = vbases_end(); VBase != E; ++VBase) {
if (const RecordType *RT = VBase->getType()->getAs<RecordType>()) {
CXXRecordDecl *VBaseClassDecl
= cast<CXXRecordDecl>(RT->getDecl());
VBaseClassDecl->getNestedVisibleConversionFunctions(RD,
TopConversionsTypeSet,
(inTopClass ? TopConversionsTypeSet : ConversionFunctions));
}
CXXRecordDecl *Base = cast<CXXRecordDecl>(RT->getDecl());
CollectVisibleConversions(Context, Base, BaseInVirtual, BaseAccess,
*HiddenTypes, Output, VOutput, HiddenVBaseCs);
}
for (CXXRecordDecl::base_class_iterator Base = bases_begin(),
E = bases_end(); Base != E; ++Base) {
if (Base->isVirtual())
continue;
if (const RecordType *RT = Base->getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(RT->getDecl());
}
BaseClassDecl->getNestedVisibleConversionFunctions(RD,
TopConversionsTypeSet,
(inTopClass ? TopConversionsTypeSet : ConversionFunctions));
}
/// Collect the visible conversions of a class.
///
/// This would be extremely straightforward if it weren't for virtual
/// bases. It might be worth special-casing that, really.
static void CollectVisibleConversions(ASTContext &Context,
CXXRecordDecl *Record,
UnresolvedSetImpl &Output) {
// The collection of all conversions in virtual bases that we've
// found. These will be added to the output as long as they don't
// appear in the hidden-conversions set.
UnresolvedSet<8> VBaseCs;
// The set of conversions in virtual bases that we've determined to
// be hidden.
llvm::SmallPtrSet<NamedDecl*, 8> HiddenVBaseCs;
// The set of types hidden by classes derived from this one.
llvm::SmallPtrSet<CanQualType, 8> HiddenTypes;
// Go ahead and collect the direct conversions and add them to the
// hidden-types set.
UnresolvedSetImpl &Cs = *Record->getConversionFunctions();
Output.append(Cs.begin(), Cs.end());
for (UnresolvedSetIterator I = Cs.begin(), E = Cs.end(); I != E; ++I)
HiddenTypes.insert(GetConversionType(Context, I.getDecl()));
// Recursively collect conversions from base classes.
for (CXXRecordDecl::base_class_iterator
I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) {
const RecordType *RT = I->getType()->getAs<RecordType>();
if (!RT) continue;
CollectVisibleConversions(Context, cast<CXXRecordDecl>(RT->getDecl()),
I->isVirtual(), I->getAccessSpecifier(),
HiddenTypes, Output, VBaseCs, HiddenVBaseCs);
}
// Add any unhidden conversions provided by virtual bases.
for (UnresolvedSetIterator I = VBaseCs.begin(), E = VBaseCs.end();
I != E; ++I) {
if (!HiddenVBaseCs.count(cast<NamedDecl>(I.getDecl()->getCanonicalDecl())))
Output.addDecl(I.getDecl(), I.getAccess());
}
}
@ -429,37 +452,27 @@ const UnresolvedSetImpl *CXXRecordDecl::getVisibleConversionFunctions() {
// If visible conversion list is already evaluated, return it.
if (data().ComputedVisibleConversions)
return &data().VisibleConversions;
llvm::SmallPtrSet<CanQualType, 8> TopConversionsTypeSet;
collectConversionFunctions(TopConversionsTypeSet);
getNestedVisibleConversionFunctions(this, TopConversionsTypeSet,
TopConversionsTypeSet);
CollectVisibleConversions(getASTContext(), this, data().VisibleConversions);
data().ComputedVisibleConversions = true;
return &data().VisibleConversions;
}
void CXXRecordDecl::addVisibleConversionFunction(
CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() &&
"Conversion function templates should cast to FunctionTemplateDecl.");
data().VisibleConversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addVisibleConversionFunction(
FunctionTemplateDecl *ConvDecl) {
assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
"Function template is not a conversion function template");
data().VisibleConversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addConversionFunction(CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() &&
"Conversion function templates should cast to FunctionTemplateDecl.");
assert(ConvDecl->getDeclContext() == this &&
"conversion function does not belong to this record");
// We intentionally don't use the decl's access here because it
// hasn't been set yet. That's really just a misdesign in Sema.
data().Conversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addConversionFunction(FunctionTemplateDecl *ConvDecl) {
assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
"Function template is not a conversion function template");
assert(ConvDecl->getDeclContext() == this &&
"conversion function does not belong to this record");
data().Conversions.addDecl(ConvDecl);
}
@ -846,28 +859,6 @@ CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
return new (C) CXXConversionDecl(RD, L, N, T, TInfo, isInline, isExplicit);
}
FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
FriendUnion Friend,
SourceLocation FriendL) {
#ifndef NDEBUG
if (Friend.is<NamedDecl*>()) {
NamedDecl *D = Friend.get<NamedDecl*>();
assert(isa<FunctionDecl>(D) ||
isa<CXXRecordDecl>(D) ||
isa<FunctionTemplateDecl>(D) ||
isa<ClassTemplateDecl>(D));
// As a temporary hack, we permit template instantiation to point
// to the original declaration when instantiating members.
assert(D->getFriendObjectKind() ||
(cast<CXXRecordDecl>(DC)->getTemplateSpecializationKind()));
}
#endif
return new (C) FriendDecl(DC, L, Friend, FriendL);
}
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
DeclContext *DC,
SourceLocation L,
@ -952,8 +943,7 @@ StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
void StaticAssertDecl::Destroy(ASTContext& C) {
AssertExpr->Destroy(C);
Message->Destroy(C);
this->~StaticAssertDecl();
C.Deallocate((void *)this);
Decl::Destroy(C);
}
StaticAssertDecl::~StaticAssertDecl() {

41
lib/AST/DeclFriend.cpp Normal file
View File

@ -0,0 +1,41 @@
//===--- DeclFriend.cpp - C++ Friend Declaration AST Node Implementation --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AST classes related to C++ friend
// declarations.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
using namespace clang;
FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
FriendUnion Friend,
SourceLocation FriendL) {
#ifndef NDEBUG
if (Friend.is<NamedDecl*>()) {
NamedDecl *D = Friend.get<NamedDecl*>();
assert(isa<FunctionDecl>(D) ||
isa<CXXRecordDecl>(D) ||
isa<FunctionTemplateDecl>(D) ||
isa<ClassTemplateDecl>(D));
// As a temporary hack, we permit template instantiation to point
// to the original declaration when instantiating members.
assert(D->getFriendObjectKind() ||
(cast<CXXRecordDecl>(DC)->getTemplateSpecializationKind()));
}
#endif
FriendDecl *FD = new (C) FriendDecl(DC, L, Friend, FriendL);
cast<CXXRecordDecl>(DC)->pushFriendDecl(FD);
return FD;
}

View File

@ -89,47 +89,69 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance) const {
return 0;
}
ObjCPropertyDecl *
ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
IdentifierInfo *propertyID) {
DeclContext::lookup_const_iterator I, E;
llvm::tie(I, E) = DC->lookup(propertyID);
for ( ; I != E; ++I)
if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I))
return PD;
return 0;
}
/// FindPropertyDeclaration - Finds declaration of the property given its name
/// in 'PropertyId' and returns it. It returns 0, if not found.
/// FIXME: Convert to DeclContext lookup...
///
ObjCPropertyDecl *
ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
for (prop_iterator I = prop_begin(), E = prop_end(); I != E; ++I)
if ((*I)->getIdentifier() == PropertyId)
return *I;
const ObjCProtocolDecl *PID = dyn_cast<ObjCProtocolDecl>(this);
if (PID) {
for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
E = PID->protocol_end(); I != E; ++I)
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
return P;
}
if (ObjCPropertyDecl *PD =
ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId))
return PD;
if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(this)) {
// Look through categories.
for (ObjCCategoryDecl *Category = OID->getCategoryList();
Category; Category = Category->getNextClassCategory()) {
if (!Category->IsClassExtension())
if (ObjCPropertyDecl *P = Category->FindPropertyDeclaration(PropertyId))
return P;
}
// Look through protocols.
for (ObjCInterfaceDecl::protocol_iterator I = OID->protocol_begin(),
E = OID->protocol_end(); I != E; ++I) {
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
return P;
}
if (OID->getSuperClass())
return OID->getSuperClass()->FindPropertyDeclaration(PropertyId);
} else if (const ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(this)) {
// Look through protocols.
if (!OCD->IsClassExtension())
for (ObjCInterfaceDecl::protocol_iterator I = OCD->protocol_begin(),
E = OCD->protocol_end(); I != E; ++I) {
switch (getKind()) {
default:
break;
case Decl::ObjCProtocol: {
const ObjCProtocolDecl *PID = cast<ObjCProtocolDecl>(this);
for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
E = PID->protocol_end(); I != E; ++I)
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
return P;
break;
}
case Decl::ObjCInterface: {
const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(this);
// Look through categories.
for (ObjCCategoryDecl *Cat = OID->getCategoryList();
Cat; Cat = Cat->getNextClassCategory())
if (!Cat->IsClassExtension())
if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(PropertyId))
return P;
// Look through protocols.
for (ObjCInterfaceDecl::protocol_iterator
I = OID->protocol_begin(), E = OID->protocol_end(); I != E; ++I)
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
return P;
// Finally, check the super class.
if (const ObjCInterfaceDecl *superClass = OID->getSuperClass())
return superClass->FindPropertyDeclaration(PropertyId);
break;
}
case Decl::ObjCCategory: {
const ObjCCategoryDecl *OCD = cast<ObjCCategoryDecl>(this);
// Look through protocols.
if (!OCD->IsClassExtension())
for (ObjCCategoryDecl::protocol_iterator
I = OCD->protocol_begin(), E = OCD->protocol_end(); I != E; ++I)
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
return P;
break;
}
}
return 0;
@ -137,22 +159,21 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
/// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
/// with name 'PropertyId' in the primary class; including those in protocols
/// (direct or indirect) used by the promary class.
/// FIXME: Convert to DeclContext lookup...
/// (direct or indirect) used by the primary class.
///
ObjCPropertyDecl *
ObjCContainerDecl::FindPropertyVisibleInPrimaryClass(
ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
IdentifierInfo *PropertyId) const {
assert(isa<ObjCInterfaceDecl>(this) && "FindPropertyVisibleInPrimaryClass");
for (prop_iterator I = prop_begin(), E = prop_end(); I != E; ++I)
if ((*I)->getIdentifier() == PropertyId)
return *I;
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(this);
if (ObjCPropertyDecl *PD =
ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId))
return PD;
// Look through protocols.
for (ObjCInterfaceDecl::protocol_iterator I = OID->protocol_begin(),
E = OID->protocol_end(); I != E; ++I)
for (ObjCInterfaceDecl::protocol_iterator
I = protocol_begin(), E = protocol_end(); I != E; ++I)
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
return P;
return 0;
}
@ -441,7 +462,6 @@ void ObjCInterfaceDecl::Destroy(ASTContext &C) {
for (ivar_iterator I = ivar_begin(), E = ivar_end(); I != E; ++I)
if (*I) (*I)->Destroy(C);
IVars.Destroy(C);
// FIXME: CategoryList?
// FIXME: Because there is no clear ownership

View File

@ -788,6 +788,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
switch (getStmtClass()) {
default:
if (getType()->isVoidType())
return false;
Loc = getExprLoc();
R1 = getSourceRange();
return true;
@ -834,8 +836,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
if (IE->getValue() == 0)
return false;
return (BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) ||
BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
return (BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) ||
BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
}
if (BO->isAssignmentOp())
@ -936,6 +938,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
if (const Expr *E = dyn_cast<Expr>(CS->body_back()))
return E->isUnusedResultAWarning(Loc, R1, R2, Ctx);
if (getType()->isVoidType())
return false;
Loc = cast<StmtExpr>(this)->getLParenLoc();
R1 = getSourceRange();
return true;
@ -949,6 +953,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
R1 = cast<CStyleCastExpr>(this)->getSubExpr()->getSourceRange();
return true;
case CXXFunctionalCastExprClass: {
if (getType()->isVoidType())
return false;
const CastExpr *CE = cast<CastExpr>(this);
// If this is a cast to void or a constructor conversion, check the operand.

View File

@ -15,7 +15,7 @@ LEVEL = ../../../..
LIBRARYNAME := clangAST
BUILD_ARCHIVE = 1
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
include $(LEVEL)/Makefile.common

View File

@ -38,17 +38,15 @@ ASTRecordLayout::ASTRecordLayout(ASTContext &Ctx, uint64_t size, unsigned alignm
// Constructor for C++ records.
ASTRecordLayout::ASTRecordLayout(ASTContext &Ctx,
uint64_t size, unsigned alignment,
uint64_t datasize,
const uint64_t *fieldoffsets,
unsigned fieldcount,
uint64_t nonvirtualsize,
unsigned nonvirtualalign,
const PrimaryBaseInfo &PrimaryBase,
const std::pair<const CXXRecordDecl *, uint64_t> *bases,
unsigned numbases,
const std::pair<const CXXRecordDecl *, uint64_t> *vbases,
unsigned numvbases)
uint64_t size, unsigned alignment,
uint64_t datasize,
const uint64_t *fieldoffsets,
unsigned fieldcount,
uint64_t nonvirtualsize,
unsigned nonvirtualalign,
const PrimaryBaseInfo &PrimaryBase,
const BaseOffsetsMapTy& BaseOffsets,
const BaseOffsetsMapTy& VBaseOffsets)
: Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
FieldCount(fieldcount), CXXInfo(new (Ctx) CXXRecordLayoutInfo)
{
@ -60,8 +58,17 @@ ASTRecordLayout::ASTRecordLayout(ASTContext &Ctx,
CXXInfo->PrimaryBase = PrimaryBase;
CXXInfo->NonVirtualSize = nonvirtualsize;
CXXInfo->NonVirtualAlign = nonvirtualalign;
for (unsigned i = 0; i != numbases; ++i)
CXXInfo->BaseOffsets[bases[i].first] = bases[i].second;
for (unsigned i = 0; i != numvbases; ++i)
CXXInfo->VBaseOffsets[vbases[i].first] = vbases[i].second;
CXXInfo->BaseOffsets = BaseOffsets;
CXXInfo->VBaseOffsets = VBaseOffsets;
#ifndef NDEBUG
if (const CXXRecordDecl *PrimaryBase = getPrimaryBase()) {
if (getPrimaryBaseWasVirtual())
assert(getVBaseClassOffset(PrimaryBase) == 0 &&
"Primary virtual base must be at offset 0!");
else
assert(getBaseClassOffset(PrimaryBase) == 0 &&
"Primary base must be at offset 0!");
}
#endif
}

View File

@ -23,43 +23,8 @@ using namespace clang;
ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
: Ctx(Ctx), Size(0), Alignment(8), Packed(false), UnfilledBitsInLastByte(0),
MaxFieldAlignment(0), DataSize(0), IsUnion(false), NonVirtualSize(0),
NonVirtualAlignment(8) { }
NonVirtualAlignment(8), FirstNearlyEmptyVBase(0) { }
/// LayoutVtable - Lay out the vtable and set PrimaryBase.
void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
if (!RD->isDynamicClass()) {
// There is no primary base in this case.
return;
}
SelectPrimaryBase(RD);
if (!PrimaryBase.getBase()) {
int AS = 0;
UpdateAlignment(Ctx.Target.getPointerAlign(AS));
Size += Ctx.Target.getPointerWidth(AS);
DataSize = Size;
}
}
void
ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
if (!i->isVirtual()) {
assert(!i->getType()->isDependentType() &&
"Cannot layout class with dependent bases.");
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
// Skip the PrimaryBase here, as it is laid down first.
if (Base != PrimaryBase.getBase() || PrimaryBase.isVirtual())
LayoutBaseNonVirtually(Base, false);
}
}
}
// Helper routines related to the abi definition from:
// http://www.codesourcery.com/public/cxx-abi/abi.html
//
/// IsNearlyEmpty - Indicates when a class has a vtable pointer, but
/// no other data.
bool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const {
@ -97,44 +62,48 @@ void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) {
}
void
ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
const CXXRecordDecl *&FirstPrimary) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
assert(!i->getType()->isDependentType() &&
ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
assert(!I->getType()->isDependentType() &&
"Cannot layout class with dependent bases.");
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (!i->isVirtual()) {
SelectPrimaryVBase(Base, FirstPrimary);
if (PrimaryBase.getBase())
return;
continue;
}
if (IsNearlyEmpty(Base)) {
if (FirstPrimary==0)
FirstPrimary = Base;
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
// Check if this is a nearly empty virtual base.
if (I->isVirtual() && IsNearlyEmpty(Base)) {
// If it's not an indirect primary base, then we've found our primary
// base.
if (!IndirectPrimaryBases.count(Base)) {
setPrimaryBase(Base, /*IsVirtual=*/true);
PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base,
/*IsVirtual=*/true);
return;
}
// Is this the first nearly empty virtual base?
if (!FirstNearlyEmptyVBase)
FirstNearlyEmptyVBase = Base;
}
assert(i->isVirtual());
SelectPrimaryVBase(Base, FirstPrimary);
SelectPrimaryVBase(Base);
if (PrimaryBase.getBase())
return;
}
}
/// SelectPrimaryBase - Selects the primary base for the given class and
/// record that with setPrimaryBase. We also calculate the IndirectPrimaries.
void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
/// DeterminePrimaryBase - Determine the primary base of the given class.
void ASTRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
// If the class isn't dynamic, it won't have a primary base.
if (!RD->isDynamicClass())
return;
// Compute all the primary virtual bases for all of our direct and
// indirect bases, and record all their primary virtual base classes.
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
assert(!i->getType()->isDependentType() &&
"Cannot layout class with dependent bases.");
"Cannot lay out class with dependent bases.");
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
IdentifyPrimaryBases(Base);
@ -161,92 +130,203 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
// Otherwise, it is the first nearly empty virtual base that is not an
// indirect primary virtual base class, if one exists.
if (RD->getNumVBases() != 0) {
SelectPrimaryVBase(RD);
if (PrimaryBase.getBase())
return;
}
// If we have no virtual bases at this point, bail out as the searching below
// is expensive.
if (RD->getNumVBases() == 0)
// Otherwise, it is the first nearly empty virtual base that is not an
// indirect primary virtual base class, if one exists.
if (FirstNearlyEmptyVBase) {
PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(FirstNearlyEmptyVBase,
/*IsVirtual=*/true);
return;
}
// Then we can search for the first nearly empty virtual base itself.
const CXXRecordDecl *FirstPrimary = 0;
SelectPrimaryVBase(RD, FirstPrimary);
// Otherwise there is no primary base class.
assert(!PrimaryBase.getBase() && "Should not get here with a primary base!");
// Otherwise if is the first nearly empty virtual base, if one exists,
// otherwise there is no primary base class.
if (!PrimaryBase.getBase())
setPrimaryBase(FirstPrimary, /*IsVirtual=*/true);
// Allocate the virtual table pointer at offset zero.
assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
// Update the size.
Size += Ctx.Target.getPointerWidth(0);
DataSize = Size;
// Update the alignment.
UpdateAlignment(Ctx.Target.getPointerAlign(0));
}
void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
LayoutBaseNonVirtually(RD, true);
}
void
ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
// First, determine the primary base class.
DeterminePrimaryBase(RD);
// If we have a primary base class, lay it out.
if (const CXXRecordDecl *Base = PrimaryBase.getBase()) {
if (PrimaryBase.isVirtual()) {
// We have a virtual primary base, insert it as an indirect primary base.
IndirectPrimaryBases.insert(Base);
uint64_t ASTRecordLayoutBuilder::getBaseOffset(const CXXRecordDecl *Base) {
for (size_t i = 0; i < Bases.size(); ++i) {
if (Bases[i].first == Base)
return Bases[i].second;
LayoutVirtualBase(Base);
} else
LayoutNonVirtualBase(Base);
}
for (size_t i = 0; i < VBases.size(); ++i) {
if (VBases[i].first == Base)
return VBases[i].second;
}
assert(0 && "missing base");
return 0;
}
// Now lay out the non-virtual bases.
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
// Ignore virtual bases.
if (I->isVirtual())
continue;
void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class,
const CXXRecordDecl *RD,
const CXXRecordDecl *PB,
uint64_t Offset,
llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
assert(!i->getType()->isDependentType() &&
"Cannot layout class with dependent bases.");
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
uint64_t BaseOffset = Offset;
if (i->isVirtual()) {
if (Base == PB) {
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
// Skip the primary base.
if (Base == PrimaryBase.getBase() && !PrimaryBase.isVirtual())
continue;
// Lay out the base.
LayoutNonVirtualBase(Base);
}
}
void ASTRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *RD) {
// Layout the base.
uint64_t Offset = LayoutBase(RD);
// Add its base class offset.
if (!Bases.insert(std::make_pair(RD, Offset)).second)
assert(false && "Added same base offset more than once!");
}
void
ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
uint64_t Offset,
const CXXRecordDecl *MostDerivedClass) {
const CXXRecordDecl *PrimaryBase;
if (MostDerivedClass == RD)
PrimaryBase = this->PrimaryBase.getBase();
else {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
PrimaryBase = Layout.getPrimaryBase();
}
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
assert(!I->getType()->isDependentType() &&
"Cannot layout class with dependent bases.");
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
if (I->isVirtual()) {
bool IndirectPrimaryBase = IndirectPrimaryBases.count(Base);
// We only want to visit this virtual base if it's either a primary base,
// or not an indirect primary base.
if (Base == PrimaryBase || !IndirectPrimaryBase) {
// Only lay things out once.
if (mark.count(Base))
if (!VisitedVirtualBases.insert(Base))
continue;
// Mark it so we don't lay it out twice.
mark.insert(Base);
assert (IndirectPrimary.count(Base) && "IndirectPrimary was wrong");
VBases.push_back(std::make_pair(Base, Offset));
} else if (IndirectPrimary.count(Base)) {
// Someone else will eventually lay this out.
;
} else {
// Only lay things out once.
if (mark.count(Base))
continue;
// Mark it so we don't lay it out twice.
mark.insert(Base);
LayoutVirtualBase(Base);
BaseOffset = VBases.back().second;
}
} else {
if (RD == Class)
BaseOffset = getBaseOffset(Base);
else {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
BaseOffset = Offset + Layout.getBaseClassOffset(Base);
if (Base == PrimaryBase) {
assert(IndirectPrimaryBase &&
"Base is supposed to be an indirect primary base!");
// We only want to add a vbase offset if this primary base is not the
// primary base of the most derived class.
if (PrimaryBase != this->PrimaryBase.getBase() ||
!this->PrimaryBase.isVirtual()) {
if (!VBases.insert(std::make_pair(Base, Offset)).second)
assert(false && "Added same vbase offset more than once!");
}
} else {
// We actually do want to lay out this base.
LayoutVirtualBase(Base);
}
}
}
if (Base->getNumVBases()) {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Base);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBaseInfo().getBase();
LayoutVirtualBases(Class, Base, PrimaryBase, BaseOffset, mark,
IndirectPrimary);
if (!Base->getNumVBases()) {
// This base isn't interesting since it doesn't have any virtual bases.
continue;
}
// Compute the offset of this base.
uint64_t BaseOffset;
if (I->isVirtual()) {
// We want the vbase offset from the class we're currently laying out.
assert(VBases.count(Base) && "Did not find virtual base!");
BaseOffset = VBases[Base];
} else if (RD == MostDerivedClass) {
// We want the base offset from the class we're currently laying out.
assert(Bases.count(Base) && "Did not find base!");
BaseOffset = Bases[Base];
} else {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
BaseOffset = Offset + Layout.getBaseClassOffset(Base);
}
LayoutVirtualBases(Base, BaseOffset, MostDerivedClass);
}
}
void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
// Layout the base.
uint64_t Offset = LayoutBase(RD);
// Add its base class offset.
if (!VBases.insert(std::make_pair(RD, Offset)).second)
assert(false && "Added same vbase offset more than once!");
}
uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
// If we have an empty base class, try to place it at offset 0.
if (RD->isEmpty() && canPlaceRecordAtOffset(RD, 0)) {
// We were able to place the class at offset 0.
UpdateEmptyClassOffsets(RD, 0);
Size = std::max(Size, BaseInfo.getSize());
return 0;
}
unsigned BaseAlign = BaseInfo.getNonVirtualAlign();
// Round up the current record size to the base's alignment boundary.
uint64_t Offset = llvm::RoundUpToAlignment(DataSize, BaseAlign);
// Try to place the base.
while (true) {
if (canPlaceRecordAtOffset(RD, Offset))
break;
Offset += BaseAlign;
}
if (!RD->isEmpty()) {
// Update the data size.
DataSize = Offset + BaseInfo.getNonVirtualSize();
Size = std::max(Size, DataSize);
} else
Size = std::max(Size, Offset + BaseInfo.getSize());
// Remember max struct/class alignment.
UpdateAlignment(BaseAlign);
UpdateEmptyClassOffsets(RD, Offset);
return Offset;
}
bool ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD,
uint64_t Offset) const {
// Look for an empty class with the same type at the same offset.
@ -393,59 +473,6 @@ ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const FieldDecl *FD,
}
}
uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
// If we have an empty base class, try to place it at offset 0.
if (RD->isEmpty() && canPlaceRecordAtOffset(RD, 0)) {
// We were able to place the class at offset 0.
UpdateEmptyClassOffsets(RD, 0);
Size = std::max(Size, BaseInfo.getSize());
return 0;
}
unsigned BaseAlign = BaseInfo.getNonVirtualAlign();
// Round up the current record size to the base's alignment boundary.
uint64_t Offset = llvm::RoundUpToAlignment(DataSize, BaseAlign);
// Try to place the base.
while (true) {
if (canPlaceRecordAtOffset(RD, Offset))
break;
Offset += BaseAlign;
}
if (!RD->isEmpty()) {
// Update the data size.
DataSize = Offset + BaseInfo.getNonVirtualSize();
Size = std::max(Size, DataSize);
} else
Size = std::max(Size, Offset + BaseInfo.getSize());
// Remember max struct/class alignment.
UpdateAlignment(BaseAlign);
UpdateEmptyClassOffsets(RD, Offset);
return Offset;
}
void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD,
bool IsVirtualBase) {
// Layout the base.
uint64_t Offset = LayoutBase(RD);
// Add base class offsets.
if (IsVirtualBase)
VBases.push_back(std::make_pair(RD, Offset));
else
Bases.push_back(std::make_pair(RD, Offset));
}
void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
IsUnion = D->isUnion();
@ -460,27 +487,17 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
// If this is a C++ class, lay out the vtable and the non-virtual bases.
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
if (RD) {
LayoutVtable(RD);
// PrimaryBase goes first.
if (PrimaryBase.getBase()) {
if (PrimaryBase.isVirtual())
IndirectPrimaryBases.insert(PrimaryBase.getBase());
LayoutBaseNonVirtually(PrimaryBase.getBase(), PrimaryBase.isVirtual());
}
if (RD)
LayoutNonVirtualBases(RD);
}
LayoutFields(D);
NonVirtualSize = Size;
NonVirtualAlignment = Alignment;
if (RD) {
llvm::SmallSet<const CXXRecordDecl*, 32> mark;
LayoutVirtualBases(RD, RD, PrimaryBase.getBase(),
0, mark, IndirectPrimaryBases);
}
// If this is a C++ class, lay out its virtual bases.
if (RD)
LayoutVirtualBases(RD, 0, RD);
// Finally, round the size of the total struct up to the alignment of the
// struct itself.
@ -697,10 +714,7 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
NonVirtualSize,
Builder.NonVirtualAlignment,
Builder.PrimaryBase,
Builder.Bases.data(),
Builder.Bases.size(),
Builder.VBases.data(),
Builder.VBases.size());
Builder.Bases, Builder.VBases);
}
const ASTRecordLayout *

View File

@ -56,21 +56,28 @@ class ASTRecordLayoutBuilder {
uint64_t NonVirtualSize;
unsigned NonVirtualAlignment;
/// PrimaryBase - the primary base class (if one exists) of the class
/// we're laying out.
ASTRecordLayout::PrimaryBaseInfo PrimaryBase;
typedef llvm::SmallVector<std::pair<const CXXRecordDecl *,
uint64_t>, 4> BaseOffsetsTy;
/// Bases - base classes and their offsets in the record.
ASTRecordLayout::BaseOffsetsMapTy Bases;
/// Bases - base classes and their offsets from the record.
BaseOffsetsTy Bases;
// VBases - virtual base classes and their offsets from the record.
BaseOffsetsTy VBases;
// VBases - virtual base classes and their offsets in the record.
ASTRecordLayout::BaseOffsetsMapTy VBases;
/// IndirectPrimaryBases - Virtual base classes, direct or indirect, that are
/// primary base classes for some other direct or indirect base class.
llvm::SmallSet<const CXXRecordDecl*, 32> IndirectPrimaryBases;
/// FirstNearlyEmptyVBase - The first nearly empty virtual base class in
/// inheritance graph order. Used for determining the primary base class.
const CXXRecordDecl *FirstNearlyEmptyVBase;
/// VisitedVirtualBases - A set of all the visited virtual bases, used to
/// avoid visiting virtual bases more than once.
llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
/// EmptyClassOffsets - A map from offsets to empty record decls.
typedef std::multimap<uint64_t, const CXXRecordDecl *> EmptyClassOffsetsTy;
EmptyClassOffsetsTy EmptyClassOffsets;
@ -86,33 +93,35 @@ class ASTRecordLayoutBuilder {
void LayoutField(const FieldDecl *D);
void LayoutBitField(const FieldDecl *D);
void SelectPrimaryBase(const CXXRecordDecl *RD);
void SelectPrimaryVBase(const CXXRecordDecl *RD,
const CXXRecordDecl *&FirstPrimary);
/// DeterminePrimaryBase - Determine the primary base of the given class.
void DeterminePrimaryBase(const CXXRecordDecl *RD);
void SelectPrimaryVBase(const CXXRecordDecl *RD);
/// IdentifyPrimaryBases - Identify all virtual base classes, direct or
/// indirect, that are primary base classes for some other direct or indirect
/// base class.
void IdentifyPrimaryBases(const CXXRecordDecl *RD);
void setPrimaryBase(const CXXRecordDecl *Base, bool IsVirtual) {
PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, IsVirtual);
}
bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
/// LayoutNonVirtualBases - Determines the primary base class (if any) and
/// lays it out. Will then proceed to lay out all non-virtual base clasess.
void LayoutNonVirtualBases(const CXXRecordDecl *RD);
/// LayoutNonVirtualBase - Lays out a single non-virtual base.
void LayoutNonVirtualBase(const CXXRecordDecl *RD);
/// LayoutVirtualBases - Lays out all the virtual bases.
void LayoutVirtualBases(const CXXRecordDecl *RD, uint64_t Offset,
const CXXRecordDecl *MostDerivedClass);
/// LayoutVirtualBase - Lays out a single virtual base.
void LayoutVirtualBase(const CXXRecordDecl *RD);
/// LayoutBase - Will lay out a base and return the offset where it was
/// placed, in bits.
uint64_t LayoutBase(const CXXRecordDecl *RD);
void LayoutVtable(const CXXRecordDecl *RD);
void LayoutNonVirtualBases(const CXXRecordDecl *RD);
void LayoutBaseNonVirtually(const CXXRecordDecl *RD, bool IsVBase);
void LayoutVirtualBase(const CXXRecordDecl *RD);
void LayoutVirtualBases(const CXXRecordDecl *Class, const CXXRecordDecl *RD,
const CXXRecordDecl *PB, uint64_t Offset,
llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary);
/// canPlaceRecordAtOffset - Return whether a record (either a base class
/// or a field) can be placed at the given offset.
@ -134,9 +143,6 @@ class ASTRecordLayoutBuilder {
/// given offset.
void UpdateEmptyClassOffsets(const FieldDecl *FD, uint64_t Offset);
/// getBaseOffset - Get the offset of a direct base class.
uint64_t getBaseOffset(const CXXRecordDecl *Base);
/// FinishLayout - Finalize record layout. Adjust record size based on the
/// alignment.
void FinishLayout();

View File

@ -474,7 +474,12 @@ void TypePrinter::PrintEnum(const EnumType *T, std::string &S) {
void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) {
Print(T->getUnderlyingType(), S);
S = std::string(T->getNameForTagKind(T->getTagKind())) + ' ' + S;
// We don't actually make these in C, but the language options
// sometimes lie to us -- for example, if someone calls
// QualType::getAsString(). Just suppress the redundant tag if so.
if (Policy.LangOpts.CPlusPlus)
S = std::string(T->getNameForTagKind(T->getTagKind())) + ' ' + S;
}
void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T,

View File

@ -15,7 +15,7 @@ LEVEL = ../../../..
LIBRARYNAME := clangAnalysis
BUILD_ARCHIVE = 1
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
include $(LEVEL)/Makefile.common

View File

@ -16,6 +16,7 @@
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
@ -81,7 +82,7 @@ namespace {
/// enabled in the specified langauge, set to 1 if it is an extension
/// in the specified language, and set to 2 if disabled in the
/// specified language.
static void AddKeyword(const char *Keyword, unsigned KWLen,
static void AddKeyword(llvm::StringRef Keyword,
tok::TokenKind TokenCode, unsigned Flags,
const LangOptions &LangOpts, IdentifierTable &Table) {
unsigned AddResult = 0;
@ -97,27 +98,27 @@ static void AddKeyword(const char *Keyword, unsigned KWLen,
// Don't add this keyword if disabled in this language.
if (AddResult == 0) return;
IdentifierInfo &Info = Table.get(Keyword, Keyword+KWLen);
IdentifierInfo &Info = Table.get(Keyword);
Info.setTokenID(TokenCode);
Info.setIsExtensionToken(AddResult == 1);
}
/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
/// representations.
static void AddCXXOperatorKeyword(const char *Keyword, unsigned KWLen,
static void AddCXXOperatorKeyword(llvm::StringRef Keyword,
tok::TokenKind TokenCode,
IdentifierTable &Table) {
IdentifierInfo &Info = Table.get(Keyword, Keyword + KWLen);
IdentifierInfo &Info = Table.get(Keyword);
Info.setTokenID(TokenCode);
Info.setIsCPlusPlusOperatorKeyword();
}
/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or
/// "property".
static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID,
const char *Name, unsigned NameLen,
static void AddObjCKeyword(llvm::StringRef Name,
tok::ObjCKeywordKind ObjCID,
IdentifierTable &Table) {
Table.get(Name, Name+NameLen).setObjCKeywordID(ObjCID);
Table.get(Name).setObjCKeywordID(ObjCID);
}
/// AddKeywords - Add all keywords to the symbol table.
@ -125,20 +126,20 @@ static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID,
void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
// Add keywords and tokens for the current language.
#define KEYWORD(NAME, FLAGS) \
AddKeyword(#NAME, strlen(#NAME), tok::kw_ ## NAME, \
AddKeyword(llvm::StringRef(#NAME), tok::kw_ ## NAME, \
FLAGS, LangOpts, *this);
#define ALIAS(NAME, TOK, FLAGS) \
AddKeyword(NAME, strlen(NAME), tok::kw_ ## TOK, \
AddKeyword(llvm::StringRef(NAME), tok::kw_ ## TOK, \
FLAGS, LangOpts, *this);
#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
if (LangOpts.CXXOperatorNames) \
AddCXXOperatorKeyword(#NAME, strlen(#NAME), tok::ALIAS, *this);
AddCXXOperatorKeyword(llvm::StringRef(#NAME), tok::ALIAS, *this);
#define OBJC1_AT_KEYWORD(NAME) \
if (LangOpts.ObjC1) \
AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
AddObjCKeyword(llvm::StringRef(#NAME), tok::objc_##NAME, *this);
#define OBJC2_AT_KEYWORD(NAME) \
if (LangOpts.ObjC2) \
AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
AddObjCKeyword(llvm::StringRef(#NAME), tok::objc_##NAME, *this);
#include "clang/Basic/TokenKinds.def"
}
@ -388,12 +389,12 @@ const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) {
case OO_None:
case NUM_OVERLOADED_OPERATORS:
return 0;
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
case OO_##Name: return Spelling;
#include "clang/Basic/OperatorKinds.def"
}
return 0;
}

View File

@ -115,9 +115,8 @@ const llvm::MemoryBuffer* FullSourceLoc::getBuffer() const {
return SrcMgr->getBuffer(SrcMgr->getFileID(*this));
}
std::pair<const char*, const char*> FullSourceLoc::getBufferData() const {
const llvm::MemoryBuffer *Buf = getBuffer();
return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd());
llvm::StringRef FullSourceLoc::getBufferData() const {
return getBuffer()->getBuffer();
}
std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const {

View File

@ -13,12 +13,16 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include <algorithm>
#include <string>
#include <cstring>
using namespace clang;
using namespace SrcMgr;
using llvm::MemoryBuffer;
@ -43,7 +47,8 @@ unsigned ContentCache::getSizeBytesMapped() const {
/// scratch buffer. If the ContentCache encapsulates a source file, that
/// file is not lazily brought in from disk to satisfy this query.
unsigned ContentCache::getSize() const {
return Buffer ? Buffer->getBufferSize() : Entry->getSize();
return Buffer ? (unsigned) Buffer->getBufferSize()
: (unsigned) Entry->getSize();
}
void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B) {
@ -53,10 +58,17 @@ void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B) {
Buffer = B;
}
const llvm::MemoryBuffer *ContentCache::getBuffer(std::string *ErrorStr) const {
const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
bool *Invalid) const {
if (Invalid)
*Invalid = false;
// Lazily create the Buffer for ContentCaches that wrap files.
if (!Buffer && Entry) {
Buffer = MemoryBuffer::getFile(Entry->getName(), ErrorStr,Entry->getSize());
std::string ErrorStr;
struct stat FileInfo;
Buffer = MemoryBuffer::getFile(Entry->getName(), &ErrorStr,
Entry->getSize(), &FileInfo);
// If we were unable to open the file, then we are in an inconsistent
// situation where the content cache referenced a file which no longer
@ -74,8 +86,27 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(std::string *ErrorStr) const {
char *Ptr = const_cast<char*>(Buffer->getBufferStart());
for (unsigned i = 0, e = Entry->getSize(); i != e; ++i)
Ptr[i] = FillStr[i % FillStr.size()];
Diag.Report(diag::err_cannot_open_file)
<< Entry->getName() << ErrorStr;
if (Invalid)
*Invalid = true;
} else {
// Check that the file's size and modification time is the same as
// in the file entry (which may have come from a stat cache).
if (FileInfo.st_size != Entry->getSize()) {
Diag.Report(diag::err_file_size_changed)
<< Entry->getName() << (unsigned)Entry->getSize()
<< (unsigned)FileInfo.st_size;
if (Invalid)
*Invalid = true;
} else if (FileInfo.st_mtime != Entry->getModificationTime()) {
Diag.Report(diag::err_file_modified) << Entry->getName();
if (Invalid)
*Invalid = true;
}
}
}
return Buffer;
}
@ -426,12 +457,11 @@ SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc,
}
const llvm::MemoryBuffer *
SourceManager::getMemoryBufferForFile(const FileEntry *File) {
SourceManager::getMemoryBufferForFile(const FileEntry *File,
bool *Invalid) {
const SrcMgr::ContentCache *IR = getOrCreateContentCache(File);
if (IR == 0)
return 0;
return IR->getBuffer();
assert(IR && "getOrCreateContentCache() cannot return NULL");
return IR->getBuffer(Diag, Invalid);
}
bool SourceManager::overrideFileContents(const FileEntry *SourceFile,
@ -444,15 +474,19 @@ bool SourceManager::overrideFileContents(const FileEntry *SourceFile,
return false;
}
/// getBufferData - Return a pointer to the start and end of the source buffer
/// data for the specified FileID.
std::pair<const char*, const char*>
SourceManager::getBufferData(FileID FID) const {
llvm::StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
if (Invalid)
*Invalid = false;
const llvm::MemoryBuffer *Buf = getBuffer(FID);
return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd());
if (!Buf) {
if (*Invalid)
*Invalid = true;
return "";
}
return Buf->getBuffer();
}
//===----------------------------------------------------------------------===//
// SourceLocation manipulation methods.
//===----------------------------------------------------------------------===//
@ -666,21 +700,34 @@ SourceManager::getInstantiationRange(SourceLocation Loc) const {
/// getCharacterData - Return a pointer to the start of the specified location
/// in the appropriate MemoryBuffer.
const char *SourceManager::getCharacterData(SourceLocation SL) const {
const char *SourceManager::getCharacterData(SourceLocation SL,
bool *Invalid) const {
// Note that this is a hot function in the getSpelling() path, which is
// heavily used by -E mode.
std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(SL);
// Note that calling 'getBuffer()' may lazily page in a source file.
return getSLocEntry(LocInfo.first).getFile().getContentCache()
->getBuffer()->getBufferStart() + LocInfo.second;
bool CharDataInvalid = false;
const llvm::MemoryBuffer *Buffer
= getSLocEntry(LocInfo.first).getFile().getContentCache()->getBuffer(Diag,
&CharDataInvalid);
if (Invalid)
*Invalid = CharDataInvalid;
return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second);
}
/// getColumnNumber - Return the column # for the specified file position.
/// this is significantly cheaper to compute than the line number.
unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos) const {
const char *Buf = getBuffer(FID)->getBufferStart();
unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
bool *Invalid) const {
bool MyInvalid = false;
const char *Buf = getBuffer(FID, &MyInvalid)->getBufferStart();
if (Invalid)
*Invalid = MyInvalid;
if (MyInvalid)
return 1;
unsigned LineStart = FilePos;
while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
@ -688,25 +735,30 @@ unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos) const {
return FilePos-LineStart+1;
}
unsigned SourceManager::getSpellingColumnNumber(SourceLocation Loc) const {
unsigned SourceManager::getSpellingColumnNumber(SourceLocation Loc,
bool *Invalid) const {
if (Loc.isInvalid()) return 0;
std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
return getColumnNumber(LocInfo.first, LocInfo.second);
return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
}
unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc) const {
unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc,
bool *Invalid) const {
if (Loc.isInvalid()) return 0;
std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
return getColumnNumber(LocInfo.first, LocInfo.second);
return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
}
static DISABLE_INLINE void ComputeLineNumbers(ContentCache* FI,
llvm::BumpPtrAllocator &Alloc);
static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){
static DISABLE_INLINE void ComputeLineNumbers(Diagnostic &Diag,
ContentCache* FI,
llvm::BumpPtrAllocator &Alloc,
bool &Invalid);
static void ComputeLineNumbers(Diagnostic &Diag, ContentCache* FI,
llvm::BumpPtrAllocator &Alloc, bool &Invalid) {
// Note that calling 'getBuffer()' may lazily page in the file.
const MemoryBuffer *Buffer = FI->getBuffer();
const MemoryBuffer *Buffer = FI->getBuffer(Diag, &Invalid);
if (Invalid)
return;
// Find the file offsets of all of the *physical* source lines. This does
// not look at trigraphs, escaped newlines, or anything else tricky.
@ -752,7 +804,8 @@ static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){
/// for the position indicated. This requires building and caching a table of
/// line offsets for the MemoryBuffer, so this is not cheap: use only when
/// about to emit a diagnostic.
unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const {
unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
bool *Invalid) const {
ContentCache *Content;
if (LastLineNoFileIDQuery == FID)
Content = LastLineNoContentCache;
@ -762,8 +815,15 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const {
// If this is the first use of line information for this buffer, compute the
/// SourceLineCache for it on demand.
if (Content->SourceLineCache == 0)
ComputeLineNumbers(Content, ContentCacheAlloc);
if (Content->SourceLineCache == 0) {
bool MyInvalid = false;
ComputeLineNumbers(Diag, Content, ContentCacheAlloc, MyInvalid);
if (Invalid)
*Invalid = MyInvalid;
if (MyInvalid)
return 1;
} else if (Invalid)
*Invalid = false;
// Okay, we know we have a line number table. Do a binary search to find the
// line number that this character position lands on.
@ -849,12 +909,14 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const {
return LineNo;
}
unsigned SourceManager::getInstantiationLineNumber(SourceLocation Loc) const {
unsigned SourceManager::getInstantiationLineNumber(SourceLocation Loc,
bool *Invalid) const {
if (Loc.isInvalid()) return 0;
std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
return getLineNumber(LocInfo.first, LocInfo.second);
}
unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc) const {
unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc,
bool *Invalid) const {
if (Loc.isInvalid()) return 0;
std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
return getLineNumber(LocInfo.first, LocInfo.second);
@ -894,10 +956,11 @@ SourceManager::getFileCharacteristic(SourceLocation Loc) const {
/// Return the filename or buffer identifier of the buffer the location is in.
/// Note that this name does not respect #line directives. Use getPresumedLoc
/// for normal clients.
const char *SourceManager::getBufferName(SourceLocation Loc) const {
const char *SourceManager::getBufferName(SourceLocation Loc,
bool *Invalid) const {
if (Loc.isInvalid()) return "<invalid loc>";
return getBuffer(getFileID(Loc))->getBufferIdentifier();
return getBuffer(getFileID(Loc), Invalid)->getBufferIdentifier();
}
@ -921,7 +984,7 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const {
// before the MemBuffer as this will avoid unnecessarily paging in the
// MemBuffer.
const char *Filename =
C->Entry ? C->Entry->getName() : C->getBuffer()->getBufferIdentifier();
C->Entry ? C->Entry->getName() : C->getBuffer(Diag)->getBufferIdentifier();
unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second);
unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second);
SourceLocation IncludeLoc = FI.getIncludeLoc();
@ -977,8 +1040,12 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
// If this is the first use of line information for this buffer, compute the
/// SourceLineCache for it on demand.
if (Content->SourceLineCache == 0)
ComputeLineNumbers(Content, ContentCacheAlloc);
if (Content->SourceLineCache == 0) {
bool MyInvalid = false;
ComputeLineNumbers(Diag, Content, ContentCacheAlloc, MyInvalid);
if (MyInvalid)
return SourceLocation();
}
// Find the first file ID that corresponds to the given file.
FileID FirstFID;
@ -1007,15 +1074,15 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
return SourceLocation();
if (Line > Content->NumLines) {
unsigned Size = Content->getBuffer()->getBufferSize();
unsigned Size = Content->getBuffer(Diag)->getBufferSize();
if (Size > 0)
--Size;
return getLocForStartOfFile(FirstFID).getFileLocWithOffset(Size);
}
unsigned FilePos = Content->SourceLineCache[Line - 1];
const char *Buf = Content->getBuffer()->getBufferStart() + FilePos;
unsigned BufLength = Content->getBuffer()->getBufferEnd() - Buf;
const char *Buf = Content->getBuffer(Diag)->getBufferStart() + FilePos;
unsigned BufLength = Content->getBuffer(Diag)->getBufferEnd() - Buf;
unsigned i = 0;
// Check that the given column is valid.

View File

@ -935,6 +935,7 @@ void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) {
.Case("sse42", SSE42)
.Case("sse41", SSE41)
.Case("ssse3", SSSE3)
.Case("sse3", SSE3)
.Case("sse2", SSE2)
.Case("sse", SSE1)
.Case("mmx", MMX)

View File

@ -19,6 +19,7 @@
#include "clang/AST/CharUnits.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManager.h"
@ -2335,7 +2336,11 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
ExplodedNodeSet Tmp;
if (InitEx) {
if (VD->getType()->isReferenceType())
if (const CXXConstructExpr *E = dyn_cast<CXXConstructExpr>(InitEx)) {
VisitCXXConstructExpr(E, GetState(Pred)->getLValue(VD,
Pred->getLocationContext()), Pred, Dst);
return;
} else if (VD->getType()->isReferenceType())
VisitLValue(InitEx, Pred, Tmp);
else
Visit(InitEx, Pred, Tmp);
@ -2826,7 +2831,8 @@ void GRExprEngine::VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst) {
// Get the this object region from StoreManager.
const MemRegion *R =
ValMgr.getRegionManager().getCXXThisRegion(TE->getType(),
ValMgr.getRegionManager().getCXXThisRegion(
getContext().getCanonicalType(TE->getType()),
Pred->getLocationContext());
const GRState *state = GetState(Pred);
@ -3126,6 +3132,78 @@ void GRExprEngine::CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,
}
}
void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
const CXXConstructorDecl *CD = E->getConstructor();
assert(CD);
if (!CD->isThisDeclarationADefinition())
// FIXME: invalidate the object.
return;
// Evaluate other arguments.
CXXConstructExpr::arg_iterator AB
= const_cast<CXXConstructExpr*>(E)->arg_begin();
CXXConstructExpr::arg_iterator AE
= const_cast<CXXConstructExpr*>(E)->arg_end();
llvm::SmallVector<CallExprWLItem, 20> WorkList;
WorkList.reserve(AE - AB);
WorkList.push_back(CallExprWLItem(AB, Pred));
ExplodedNodeSet ArgsEvaluated;
const FunctionProtoType *Proto = CD->getType()->getAs<FunctionProtoType>();
while (!WorkList.empty()) {
CallExprWLItem Item = WorkList.back();
WorkList.pop_back();
if (Item.I == AE) {
ArgsEvaluated.insert(Item.N);
continue;
}
// Evaluate the argument.
ExplodedNodeSet Tmp;
const unsigned ParamIdx = Item.I - AB;
bool VisitAsLvalue = false;
if (ParamIdx < Proto->getNumArgs())
VisitAsLvalue = Proto->getArgType(ParamIdx)->isReferenceType();
if (VisitAsLvalue)
VisitLValue(*Item.I, Item.N, Tmp);
else
Visit(*Item.I, Item.N, Tmp);
++(Item.I);
for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
WorkList.push_back(CallExprWLItem(Item.I, *NI));
}
// The callee stack frame context used to create the 'this' parameter region.
const StackFrameContext *SFC = AMgr.getStackFrame(CD,
Pred->getLocationContext(),
E, Builder->getBlock(), Builder->getIndex());
Type *T = CD->getParent()->getTypeForDecl();
QualType PT = getContext().getPointerType(QualType(T,0));
const CXXThisRegion *ThisR = ValMgr.getRegionManager().getCXXThisRegion(PT,
SFC);
CallEnter Loc(E, CD, Pred->getLocationContext());
for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(),
NE = ArgsEvaluated.end(); NI != NE; ++NI) {
const GRState *state = GetState(*NI);
// Setup 'this' region.
state = state->bindLoc(loc::MemRegionVal(ThisR), Dest);
ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
if (N)
Dst.Add(N);
}
}
//===----------------------------------------------------------------------===//
// Checker registration/lookup.
//===----------------------------------------------------------------------===//

View File

@ -15,7 +15,7 @@ LEVEL = ../../../..
LIBRARYNAME := clangChecker
BUILD_ARCHIVE = 1
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
include $(LEVEL)/Makefile.common

View File

@ -22,6 +22,8 @@
#include "clang/Analysis/Support/Optional.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/ImmutableList.h"
@ -29,8 +31,6 @@
using namespace clang;
#define USE_EXPLICIT_COMPOUND 0
//===----------------------------------------------------------------------===//
// Representation of binding keys.
//===----------------------------------------------------------------------===//
@ -1336,54 +1336,13 @@ SVal RegionStoreManager::RetrieveLazySymbol(const TypedRegion *R) {
SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
QualType T = R->getValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = T->getAsStructureType();
RecordDecl* RD = RT->getDecl();
assert(RD->isDefinition());
(void)RD;
#if USE_EXPLICIT_COMPOUND
llvm::ImmutableList<SVal> StructVal = getBasicVals().getEmptySValList();
// FIXME: We shouldn't use a std::vector. If RecordDecl doesn't have a
// reverse iterator, we should implement one.
std::vector<FieldDecl *> Fields(RD->field_begin(), RD->field_end());
for (std::vector<FieldDecl *>::reverse_iterator Field = Fields.rbegin(),
FieldEnd = Fields.rend();
Field != FieldEnd; ++Field) {
FieldRegion* FR = MRMgr.getFieldRegion(*Field, R);
QualType FTy = (*Field)->getType();
SVal FieldValue = Retrieve(store, loc::MemRegionVal(FR), FTy).getSVal();
StructVal = getBasicVals().consVals(FieldValue, StructVal);
}
return ValMgr.makeCompoundVal(T, StructVal);
#else
assert(T->getAsStructureType()->getDecl()->isDefinition());
return ValMgr.makeLazyCompoundVal(store, R);
#endif
}
SVal RegionStoreManager::RetrieveArray(Store store, const TypedRegion * R) {
#if USE_EXPLICIT_COMPOUND
QualType T = R->getValueType(getContext());
ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
llvm::ImmutableList<SVal> ArrayVal = getBasicVals().getEmptySValList();
uint64_t size = CAT->getSize().getZExtValue();
for (uint64_t i = 0; i < size; ++i) {
SVal Idx = ValMgr.makeArrayIndex(i);
ElementRegion* ER = MRMgr.getElementRegion(CAT->getElementType(), Idx, R,
getContext());
QualType ETy = ER->getElementType();
SVal ElementVal = Retrieve(store, loc::MemRegionVal(ER), ETy).getSVal();
ArrayVal = getBasicVals().consVals(ElementVal, ArrayVal);
}
return ValMgr.makeCompoundVal(T, ArrayVal);
#else
assert(isa<ConstantArrayType>(R->getValueType(getContext())));
return ValMgr.makeLazyCompoundVal(store, R);
#endif
}
//===----------------------------------------------------------------------===//
@ -1884,18 +1843,29 @@ Store RegionStoreManager::RemoveDeadBindings(Store store, Stmt* Loc,
GRState const *RegionStoreManager::EnterStackFrame(GRState const *state,
StackFrameContext const *frame) {
FunctionDecl const *FD = cast<FunctionDecl>(frame->getDecl());
CallExpr const *CE = cast<CallExpr>(frame->getCallSite());
FunctionDecl::param_const_iterator PI = FD->param_begin();
CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
// Copy the arg expression value to the arg variables.
Store store = state->getStore();
for (; AI != AE; ++AI, ++PI) {
SVal ArgVal = state->getSVal(*AI);
store = Bind(store, ValMgr.makeLoc(MRMgr.getVarRegion(*PI, frame)), ArgVal);
}
if (CallExpr const *CE = dyn_cast<CallExpr>(frame->getCallSite())) {
CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
// Copy the arg expression value to the arg variables.
for (; AI != AE; ++AI, ++PI) {
SVal ArgVal = state->getSVal(*AI);
store = Bind(store, ValMgr.makeLoc(MRMgr.getVarRegion(*PI,frame)),ArgVal);
}
} else if (const CXXConstructExpr *CE =
dyn_cast<CXXConstructExpr>(frame->getCallSite())) {
CXXConstructExpr::const_arg_iterator AI = CE->arg_begin(),
AE = CE->arg_end();
// Copy the arg expression value to the arg variables.
for (; AI != AE; ++AI, ++PI) {
SVal ArgVal = state->getSVal(*AI);
store = Bind(store, ValMgr.makeLoc(MRMgr.getVarRegion(*PI,frame)),ArgVal);
}
} else
assert(0 && "Unhandled call expression.");
return state->makeWithStore(store);
}

View File

@ -98,7 +98,7 @@ CodeGenModule::ComputeThunkAdjustment(const CXXRecordDecl *ClassDecl,
}
if (VBase)
VirtualOffset =
getVtableInfo().getVirtualBaseOffsetIndex(ClassDecl, BaseClassDecl);
getVtableInfo().getVirtualBaseOffsetOffset(ClassDecl, BaseClassDecl);
uint64_t Offset =
ComputeNonVirtualBaseClassOffset(getContext(), Paths.front(), Start);
@ -1540,11 +1540,11 @@ CodeGenFunction::GetVirtualBaseClassOffset(llvm::Value *This,
Int8PtrTy->getPointerTo());
VTablePtr = Builder.CreateLoad(VTablePtr, "vtable");
int64_t VBaseOffsetIndex =
CGM.getVtableInfo().getVirtualBaseOffsetIndex(ClassDecl, BaseClassDecl);
int64_t VBaseOffsetOffset =
CGM.getVtableInfo().getVirtualBaseOffsetOffset(ClassDecl, BaseClassDecl);
llvm::Value *VBaseOffsetPtr =
Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetIndex, "vbase.offset.ptr");
Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetOffset, "vbase.offset.ptr");
const llvm::Type *PtrDiffTy =
ConvertType(getContext().getPointerDiffType());

View File

@ -104,7 +104,10 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
void CGDebugInfo::CreateCompileUnit() {
// Get absolute path name.
llvm::sys::Path AbsFileName(CGM.getCodeGenOpts().MainFileName);
std::string MainFileName = CGM.getCodeGenOpts().MainFileName;
if (MainFileName.empty())
MainFileName = "<unknown>";
llvm::sys::Path AbsFileName(MainFileName);
AbsFileName.makeAbsolute();
unsigned LangTag;
@ -649,9 +652,9 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
cast<CXXRecordDecl>(BI->getType()->getAs<RecordType>()->getDecl());
if (BI->isVirtual()) {
// virtual base offset index is -ve. The code generator emits dwarf
// virtual base offset offset is -ve. The code generator emits dwarf
// expression where it expects +ve number.
BaseOffset = 0 - CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base);
BaseOffset = 0 - CGM.getVtableInfo().getVirtualBaseOffsetOffset(RD, Base);
BFlags = llvm::DIType::FlagVirtual;
} else
BaseOffset = RL.getBaseClassOffset(Base);
@ -774,9 +777,8 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
// A RD->getName() is not unique. However, the debug info descriptors
// are uniqued so use type name to ensure uniquness.
llvm::SmallString<256> FwdDeclName;
FwdDeclName.resize(256);
sprintf(&FwdDeclName[0], "fwd.type.%d", FwdDeclCount++);
llvm::SmallString<128> FwdDeclName;
llvm::raw_svector_ostream(FwdDeclName) << "fwd.type." << FwdDeclCount++;
llvm::DIDescriptor FDContext =
getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()), Unit);
llvm::DICompositeType FwdDecl =
@ -792,6 +794,9 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
// Otherwise, insert it into the TypeCache so that recursive uses will find
// it.
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl.getNode();
// Push the struct on region stack.
RegionStack.push_back(FwdDecl.getNode());
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl.getNode());
// Convert all the elements.
llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
@ -822,6 +827,12 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
RegionStack.pop_back();
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI =
RegionMap.find(Ty->getDecl());
if (RI != RegionMap.end())
RegionMap.erase(RI);
llvm::DIDescriptor RDContext =
getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()), Unit);
llvm::DICompositeType RealDecl =
@ -834,7 +845,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
// Now that we have a real decl for the struct, replace anything using the
// old decl with the new one. This will recursively update the debug info.
llvm::DIDerivedType(FwdDeclNode).replaceAllUsesWith(RealDecl);
RegionMap[RD] = llvm::WeakVH(RealDecl.getNode());
return RealDecl;
}
@ -874,6 +885,9 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// Otherwise, insert it into the TypeCache so that recursive uses will find
// it.
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl.getNode();
// Push the struct on region stack.
RegionStack.push_back(FwdDecl.getNode());
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl.getNode());
// Convert all the elements.
llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
@ -946,6 +960,12 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
llvm::DIArray Elements =
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
RegionStack.pop_back();
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI =
RegionMap.find(Ty->getDecl());
if (RI != RegionMap.end())
RegionMap.erase(RI);
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
@ -958,6 +978,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// Now that we have a real decl for the struct, replace anything using the
// old decl with the new one. This will recursively update the debug info.
llvm::DIDerivedType(FwdDeclNode).replaceAllUsesWith(RealDecl);
RegionMap[ID] = llvm::WeakVH(RealDecl.getNode());
return RealDecl;
}

View File

@ -211,6 +211,8 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D,
if (D.getInit())
GV = AddInitializerToGlobalBlockVarDecl(D, GV);
GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
// FIXME: Merge attribute handling.
if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>()) {
SourceManager &SM = CGM.getContext().getSourceManager();
@ -471,68 +473,6 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
EnsureInsertPoint();
}
if (Init) {
llvm::Value *Loc = DeclPtr;
if (isByRef)
Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
D.getNameAsString());
bool isVolatile =
getContext().getCanonicalType(D.getType()).isVolatileQualified();
// If the initializer was a simple constant initializer, we can optimize it
// in various ways.
if (IsSimpleConstantInitializer) {
llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(),D.getType(),this);
assert(Init != 0 && "Wasn't a simple constant init?");
llvm::Value *AlignVal =
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
Align.getQuantity());
const llvm::Type *IntPtr =
llvm::IntegerType::get(VMContext, LLVMPointerWidth);
llvm::Value *SizeVal =
llvm::ConstantInt::get(IntPtr,
getContext().getTypeSizeInChars(Ty).getQuantity());
const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext);
if (Loc->getType() != BP)
Loc = Builder.CreateBitCast(Loc, BP, "tmp");
// If the initializer is all zeros, codegen with memset.
if (isa<llvm::ConstantAggregateZero>(Init)) {
llvm::Value *Zero =
llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 0);
Builder.CreateCall4(CGM.getMemSetFn(), Loc, Zero, SizeVal, AlignVal);
} else {
// Otherwise, create a temporary global with the initializer then
// memcpy from the global to the alloca.
std::string Name = GetStaticDeclName(*this, D, ".");
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(CGM.getModule(), Init->getType(), true,
llvm::GlobalValue::InternalLinkage,
Init, Name, 0, false, 0);
GV->setAlignment(Align.getQuantity());
llvm::Value *SrcPtr = GV;
if (SrcPtr->getType() != BP)
SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
Builder.CreateCall4(CGM.getMemCpyFn(), Loc, SrcPtr, SizeVal, AlignVal);
}
} else if (Ty->isReferenceType()) {
RValue RV = EmitReferenceBindingToExpr(Init, /*IsInitializer=*/true);
EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Ty);
} else if (!hasAggregateLLVMType(Init->getType())) {
llvm::Value *V = EmitScalarExpr(Init);
EmitStoreOfScalar(V, Loc, isVolatile, D.getType());
} else if (Init->getType()->isAnyComplexType()) {
EmitComplexExprIntoAddr(Init, Loc, isVolatile);
} else {
EmitAggExpr(Init, Loc, isVolatile);
}
}
if (isByRef) {
const llvm::PointerType *PtrToInt8Ty = llvm::Type::getInt8PtrTy(VMContext);
@ -591,6 +531,68 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
}
}
if (Init) {
llvm::Value *Loc = DeclPtr;
if (isByRef)
Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
D.getNameAsString());
bool isVolatile =
getContext().getCanonicalType(D.getType()).isVolatileQualified();
// If the initializer was a simple constant initializer, we can optimize it
// in various ways.
if (IsSimpleConstantInitializer) {
llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(),D.getType(),this);
assert(Init != 0 && "Wasn't a simple constant init?");
llvm::Value *AlignVal =
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
Align.getQuantity());
const llvm::Type *IntPtr =
llvm::IntegerType::get(VMContext, LLVMPointerWidth);
llvm::Value *SizeVal =
llvm::ConstantInt::get(IntPtr,
getContext().getTypeSizeInChars(Ty).getQuantity());
const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext);
if (Loc->getType() != BP)
Loc = Builder.CreateBitCast(Loc, BP, "tmp");
// If the initializer is all zeros, codegen with memset.
if (isa<llvm::ConstantAggregateZero>(Init)) {
llvm::Value *Zero =
llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 0);
Builder.CreateCall4(CGM.getMemSetFn(), Loc, Zero, SizeVal, AlignVal);
} else {
// Otherwise, create a temporary global with the initializer then
// memcpy from the global to the alloca.
std::string Name = GetStaticDeclName(*this, D, ".");
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(CGM.getModule(), Init->getType(), true,
llvm::GlobalValue::InternalLinkage,
Init, Name, 0, false, 0);
GV->setAlignment(Align.getQuantity());
llvm::Value *SrcPtr = GV;
if (SrcPtr->getType() != BP)
SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
Builder.CreateCall4(CGM.getMemCpyFn(), Loc, SrcPtr, SizeVal, AlignVal);
}
} else if (Ty->isReferenceType()) {
RValue RV = EmitReferenceBindingToExpr(Init, /*IsInitializer=*/true);
EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Ty);
} else if (!hasAggregateLLVMType(Init->getType())) {
llvm::Value *V = EmitScalarExpr(Init);
EmitStoreOfScalar(V, Loc, isVolatile, D.getType());
} else if (Init->getType()->isAnyComplexType()) {
EmitComplexExprIntoAddr(Init, Loc, isVolatile);
} else {
EmitAggExpr(Init, Loc, isVolatile);
}
}
// Handle CXX destruction of variables.
QualType DtorTy(Ty);
while (const ArrayType *Array = getContext().getAsArrayType(DtorTy))

View File

@ -1147,8 +1147,8 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
// Collect the names of referenced protocols
llvm::SmallVector<std::string, 16> Protocols;
const ObjCInterfaceDecl *ClassDecl = OCD->getClassInterface();
const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
const ObjCCategoryDecl *CatDecl = OCD->getCategoryDecl();
const ObjCList<ObjCProtocolDecl> &Protos = CatDecl->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
E = Protos.end(); I != E; ++I)
Protocols.push_back((*I)->getNameAsString());

View File

@ -760,7 +760,7 @@ void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
// subobject. For a virtual base, this is the offset in the virtual table of
// the virtual base offset for the virtual base referenced (negative).
if (Base->isVirtual())
OffsetFlags = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, BaseDecl);
OffsetFlags = CGM.getVtableInfo().getVirtualBaseOffsetOffset(RD, BaseDecl);
else {
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
OffsetFlags = Layout.getBaseClassOffset(BaseDecl) / 8;

View File

@ -63,10 +63,7 @@ class FinalOverriders {
/// Offset - the base offset of the overrider in the layout class.
uint64_t Offset;
/// OldOffset - FIXME: Remove this.
int64_t OldOffset;
OverriderInfo() : Method(0), Offset(0), OldOffset(0) { }
OverriderInfo() : Method(0), Offset(0) { }
};
private:
@ -251,7 +248,6 @@ void FinalOverriders::AddOverriders(BaseSubobject Base,
OverriderInfo& Overrider = OverridersMap[std::make_pair(Base, MD)];
assert(!Overrider.Method && "Overrider should not exist yet!");
Overrider.OldOffset = Base.getBaseOffset();
Overrider.Offset = OffsetInLayoutClass;
Overrider.Method = MD;
}
@ -415,7 +411,6 @@ void FinalOverriders::PropagateOverrider(const CXXMethodDecl *OldMD,
// Set the new overrider.
Overrider.Offset = OverriderOffsetInLayoutClass;
Overrider.OldOffset = NewBase.getBaseOffset();
Overrider.Method = NewMD;
// And propagate it further.
@ -559,7 +554,7 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) {
Out << " " << MD->getQualifiedNameAsString() << " - (";
Out << Overrider.Method->getQualifiedNameAsString();
Out << ", " << Overrider.OldOffset / 8 << ", " << Overrider.Offset / 8 << ')';
Out << ", " << ", " << Overrider.Offset / 8 << ')';
AdjustmentOffsetsMapTy::const_iterator AI =
ReturnAdjustments.find(std::make_pair(Base, MD));
@ -834,6 +829,11 @@ int64_t VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) {
/// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets.
class VCallAndVBaseOffsetBuilder {
public:
typedef llvm::DenseMap<const CXXRecordDecl *, int64_t>
VBaseOffsetOffsetsMapTy;
private:
/// MostDerivedClass - The most derived class for which we're building vcall
/// and vbase offsets.
const CXXRecordDecl *MostDerivedClass;
@ -856,6 +856,11 @@ class VCallAndVBaseOffsetBuilder {
/// VCallOffsets - Keeps track of vcall offsets.
VCallOffsetMap VCallOffsets;
/// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets,
/// relative to the address point.
VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
/// FinalOverriders - The final overriders of the most derived class.
/// (Can be null when we're not building a vtable of the most derived class).
const FinalOverriders *Overriders;
@ -871,6 +876,10 @@ class VCallAndVBaseOffsetBuilder {
/// AddVBaseOffsets - Add vbase offsets for the given class.
void AddVBaseOffsets(const CXXRecordDecl *Base, uint64_t OffsetInLayoutClass);
/// getCurrentOffsetOffset - Get the current vcall or vbase offset offset in
/// bytes, relative to the vtable address point.
int64_t getCurrentOffsetOffset() const;
public:
VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass,
const CXXRecordDecl *LayoutClass,
@ -889,7 +898,10 @@ class VCallAndVBaseOffsetBuilder {
const_iterator components_begin() const { return Components.rbegin(); }
const_iterator components_end() const { return Components.rend(); }
const VCallOffsetMap& getVCallOffsets() const { return VCallOffsets; }
const VCallOffsetMap &getVCallOffsets() const { return VCallOffsets; }
const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
return VBaseOffsetOffsets;
}
};
void
@ -940,6 +952,20 @@ VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
AddVCallOffsets(Base, RealBaseOffset);
}
int64_t VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const {
// OffsetIndex is the index of this vcall or vbase offset, relative to the
// vtable address point. (We subtract 3 to account for the information just
// above the address point, the RTTI info, the offset to top, and the
// vcall offset itself).
int64_t OffsetIndex = -(int64_t)(3 + Components.size());
// FIXME: We shouldn't use / 8 here.
int64_t OffsetOffset = OffsetIndex *
(int64_t)Context.Target.getPointerWidth(0) / 8;
return OffsetOffset;
}
void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
uint64_t VBaseOffset) {
const CXXRecordDecl *RD = Base.getBase();
@ -980,15 +1006,7 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
if (!MD->isVirtual())
continue;
// OffsetIndex is the index of this vcall offset, relative to the vtable
// address point. (We subtract 3 to account for the information just
// above the address point, the RTTI info, the offset to top, and the
// vcall offset itself).
int64_t OffsetIndex = -(int64_t)(3 + Components.size());
// FIXME: We shouldn't use / 8 here.
int64_t OffsetOffset = OffsetIndex *
(int64_t)Context.Target.getPointerWidth(0) / 8;
int64_t OffsetOffset = getCurrentOffsetOffset();
// Don't add a vcall offset if we already have one for this member function
// signature.
@ -1048,10 +1066,17 @@ void VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
int64_t Offset =
(int64_t)(LayoutClassLayout.getVBaseClassOffset(BaseDecl) -
OffsetInLayoutClass) / 8;
// Add the vbase offset offset.
assert(!VBaseOffsetOffsets.count(BaseDecl) &&
"vbase offset offset already exists!");
int64_t VBaseOffsetOffset = getCurrentOffsetOffset();
VBaseOffsetOffsets.insert(std::make_pair(BaseDecl, VBaseOffsetOffset));
Components.push_back(VtableComponent::MakeVBaseOffset(Offset));
}
// Check the base class looking for more vbase offsets.
AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
}
@ -1096,6 +1121,13 @@ class VtableBuilder {
/// bases in this vtable.
llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
typedef llvm::DenseMap<const CXXRecordDecl *, int64_t>
VBaseOffsetOffsetsMapTy;
/// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for
/// the most derived class.
VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
/// Components - The components of the vtable being built.
llvm::SmallVector<VtableComponent, 64> Components;
@ -1117,24 +1149,27 @@ class VtableBuilder {
bool isEmpty() const { return !NonVirtual && !VBaseOffsetOffset; }
};
/// ReturnAdjustments - The return adjustments needed in this vtable.
llvm::SmallVector<std::pair<uint64_t, ReturnAdjustment>, 16>
ReturnAdjustments;
/// MethodInfo - Contains information about a method in a vtable.
/// (Used for computing 'this' pointer adjustment thunks.
struct MethodInfo {
/// BaseOffset - The base offset of this method.
const uint64_t BaseOffset;
/// BaseOffsetInLayoutClass - The base offset in the layout class of this
/// method.
const uint64_t BaseOffsetInLayoutClass;
/// VtableIndex - The index in the vtable that this method has.
/// (For destructors, this is the index of the complete destructor).
const uint64_t VtableIndex;
MethodInfo(uint64_t BaseOffset, uint64_t VtableIndex)
: BaseOffset(BaseOffset), VtableIndex(VtableIndex) { }
MethodInfo(uint64_t BaseOffset, uint64_t BaseOffsetInLayoutClass,
uint64_t VtableIndex)
: BaseOffset(BaseOffset),
BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
VtableIndex(VtableIndex) { }
MethodInfo() : BaseOffset(0), VtableIndex(0) { }
MethodInfo() : BaseOffset(0), BaseOffsetInLayoutClass(0), VtableIndex(0) { }
};
typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
@ -1158,9 +1193,27 @@ class VtableBuilder {
bool isEmpty() const { return !NonVirtual && !VCallOffsetOffset; }
};
/// ThisAdjustments - The 'this' pointer adjustments needed in this vtable.
llvm::SmallVector<std::pair<uint64_t, ThisAdjustment>, 16>
ThisAdjustments;
/// ThunkInfo - The 'this' pointer adjustment as well as an optional return
/// adjustment for a thunk.
struct ThunkInfo {
/// This - The 'this' pointer adjustment.
ThisAdjustment This;
/// Return - The return adjustment.
ReturnAdjustment Return;
ThunkInfo() { }
ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return)
: This(This), Return(Return) { }
bool isEmpty() const { return This.isEmpty() && Return.isEmpty(); }
};
typedef llvm::DenseMap<uint64_t, ThunkInfo> ThunksInfoMapTy;
/// Thunks - The thunks by vtable index in the vtable currently being built.
ThunksInfoMapTy Thunks;
/// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the
/// part of the vtable we're currently building.
@ -1182,11 +1235,13 @@ class VtableBuilder {
BaseSubobject Derived) const;
/// ComputeThisAdjustment - Compute the 'this' pointer adjustment for the
/// given virtual member function and the 'this' pointer adjustment base
/// offset.
ThisAdjustment ComputeThisAdjustment(const CXXMethodDecl *MD,
BaseOffset Offset);
/// given virtual member function, its offset in the layout class and its
/// final overrider.
ThisAdjustment
ComputeThisAdjustment(const CXXMethodDecl *MD,
uint64_t BaseOffsetInLayoutClass,
FinalOverriders::OverriderInfo Overrider);
/// AddMethod - Add a single virtual member function to the vtable
/// components vector.
void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment);
@ -1235,7 +1290,11 @@ class VtableBuilder {
/// LayoutSecondaryVtables - Layout the secondary vtables for the given base
/// subobject.
void LayoutSecondaryVtables(BaseSubobject Base, uint64_t OffsetInLayoutClass);
///
/// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
/// or a direct or indirect base of a virtual base.
void LayoutSecondaryVtables(BaseSubobject Base, bool BaseIsMorallyVirtual,
uint64_t OffsetInLayoutClass);
/// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
/// class hierarchy.
@ -1292,8 +1351,6 @@ OverridesMethodInBases(const CXXMethodDecl *MD,
}
void VtableBuilder::ComputeThisAdjustments() {
std::map<uint64_t, ThisAdjustment> SortedThisAdjustments;
// Now go through the method info map and see if any of the methods need
// 'this' pointer adjustments.
for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
@ -1301,56 +1358,34 @@ void VtableBuilder::ComputeThisAdjustments() {
const CXXMethodDecl *MD = I->first;
const MethodInfo &MethodInfo = I->second;
BaseSubobject OverriddenBaseSubobject(MD->getParent(),
MethodInfo.BaseOffset);
// Get the final overrider for this method.
FinalOverriders::OverriderInfo Overrider =
Overriders.getOverrider(OverriddenBaseSubobject, MD);
// Check if we need an adjustment.
if (Overrider.OldOffset == (int64_t)MethodInfo.BaseOffset)
continue;
uint64_t VtableIndex = MethodInfo.VtableIndex;
// Ignore adjustments for pure virtual member functions.
if (Overrider.Method->isPure())
continue;
// Ignore adjustments for unused function pointers.
uint64_t VtableIndex = MethodInfo.VtableIndex;
if (Components[VtableIndex].getKind() ==
VtableComponent::CK_UnusedFunctionPointer)
continue;
// Get the final overrider for this method.
FinalOverriders::OverriderInfo Overrider =
Overriders.getOverrider(BaseSubobject(MD->getParent(),
MethodInfo.BaseOffset), MD);
ThisAdjustment ThisAdjustment =
ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
Overrider.OldOffset);
// Compute the adjustment offset.
BaseOffset ThisAdjustmentOffset =
ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
OverriderBaseSubobject);
// Then compute the adjustment itself.
ThisAdjustment ThisAdjustment = ComputeThisAdjustment(Overrider.Method,
ThisAdjustmentOffset);
if (ThisAdjustment.isEmpty())
continue;
// Add it.
SortedThisAdjustments.insert(std::make_pair(VtableIndex, ThisAdjustment));
Thunks[VtableIndex].This = ThisAdjustment;
if (isa<CXXDestructorDecl>(MD)) {
// Add an adjustment for the deleting destructor as well.
SortedThisAdjustments.insert(std::make_pair(VtableIndex + 1,
ThisAdjustment));
Thunks[VtableIndex + 1].This = ThisAdjustment;
}
}
/// Clear the method info map.
MethodInfoMap.clear();
// Add the sorted elements.
ThisAdjustments.append(SortedThisAdjustments.begin(),
SortedThisAdjustments.end());
}
VtableBuilder::ReturnAdjustment
@ -1360,13 +1395,20 @@ VtableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
if (!Offset.isEmpty()) {
if (Offset.VirtualBase) {
// Get the virtual base offset offset.
Adjustment.VBaseOffsetOffset =
VtableInfo.getVirtualBaseOffsetIndex(Offset.DerivedClass,
Offset.VirtualBase);
// FIXME: Once the assert in getVirtualBaseOffsetIndex is back again,
if (Offset.DerivedClass == MostDerivedClass) {
// We can get the offset offset directly from our map.
Adjustment.VBaseOffsetOffset =
VBaseOffsetOffsets.lookup(Offset.VirtualBase);
} else {
Adjustment.VBaseOffsetOffset =
VtableInfo.getVirtualBaseOffsetOffset(Offset.DerivedClass,
Offset.VirtualBase);
}
// FIXME: Once the assert in getVirtualBaseOffsetOffset is back again,
// we can get rid of this assert.
assert(Adjustment.VBaseOffsetOffset != 0 &&
"Invalid base offset offset!");
"Invalid vbase offset offset!");
}
Adjustment.NonVirtual = Offset.NonVirtualOffset;
@ -1402,13 +1444,13 @@ VtableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
if (Offset.VirtualBase) {
// If we have a virtual base class, the non-virtual offset is relative
// to the virtual base class offset.
const ASTRecordLayout &MostDerivedClassLayout =
Context.getASTRecordLayout(MostDerivedClass);
const ASTRecordLayout &LayoutClassLayout =
Context.getASTRecordLayout(LayoutClass);
/// Get the virtual base offset, relative to the most derived class
/// layout.
OffsetToBaseSubobject +=
MostDerivedClassLayout.getVBaseClassOffset(Offset.VirtualBase);
LayoutClassLayout.getVBaseClassOffset(Offset.VirtualBase);
} else {
// Otherwise, the non-virtual offset is relative to the derived class
// offset.
@ -1427,38 +1469,57 @@ VtableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
return BaseOffset();
}
VtableBuilder::ThisAdjustment
VtableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD,
uint64_t BaseOffsetInLayoutClass,
FinalOverriders::OverriderInfo Overrider) {
// Check if we need an adjustment at all.
if (BaseOffsetInLayoutClass == Overrider.Offset)
return ThisAdjustment();
// Ignore adjustments for pure virtual member functions.
if (Overrider.Method->isPure())
return ThisAdjustment();
BaseSubobject OverriddenBaseSubobject(MD->getParent(),
BaseOffsetInLayoutClass);
BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
Overrider.Offset);
// Compute the adjustment offset.
BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
OverriderBaseSubobject);
if (Offset.isEmpty())
return ThisAdjustment();
VtableBuilder::ThisAdjustment
VtableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD,
BaseOffset Offset) {
ThisAdjustment Adjustment;
if (!Offset.isEmpty()) {
if (Offset.VirtualBase) {
// Get the vcall offset map for this virtual base.
VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
if (VCallOffsets.empty()) {
// We don't have vcall offsets for this virtual base, go ahead and
// build them.
VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
/*FinalOverriders=*/0,
BaseSubobject(Offset.VirtualBase, 0),
/*BaseIsVirtual=*/true,
/*OffsetInLayoutClass=*/0);
VCallOffsets = Builder.getVCallOffsets();
}
Adjustment.VCallOffsetOffset = VCallOffsets.getVCallOffsetOffset(MD);
}
if (Offset.VirtualBase) {
// Get the vcall offset map for this virtual base.
VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
Adjustment.NonVirtual = Offset.NonVirtualOffset;
if (VCallOffsets.empty()) {
// We don't have vcall offsets for this virtual base, go ahead and
// build them.
VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
/*FinalOverriders=*/0,
BaseSubobject(Offset.VirtualBase, 0),
/*BaseIsVirtual=*/true,
/*OffsetInLayoutClass=*/0);
VCallOffsets = Builder.getVCallOffsets();
}
Adjustment.VCallOffsetOffset = VCallOffsets.getVCallOffsetOffset(MD);
}
// Set the non-virtual part of the adjustment.
Adjustment.NonVirtual = Offset.NonVirtualOffset;
return Adjustment;
}
void
VtableBuilder::AddMethod(const CXXMethodDecl *MD,
ReturnAdjustment ReturnAdjustment) {
@ -1472,8 +1533,7 @@ VtableBuilder::AddMethod(const CXXMethodDecl *MD,
} else {
// Add the return adjustment if necessary.
if (!ReturnAdjustment.isEmpty())
ReturnAdjustments.push_back(std::make_pair(Components.size(),
ReturnAdjustment));
Thunks[Components.size()].Return = ReturnAdjustment;
// Add the function.
Components.push_back(VtableComponent::MakeFunction(MD));
@ -1665,6 +1725,7 @@ VtableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass,
MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
MethodInfo MethodInfo(Base.getBaseOffset(),
BaseOffsetInLayoutClass,
OverriddenMethodInfo.VtableIndex);
assert(!MethodInfoMap.count(MD) &&
@ -1677,7 +1738,8 @@ VtableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass,
}
// Insert the method info for this method.
MethodInfo MethodInfo(Base.getBaseOffset(), Components.size());
MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
Components.size());
assert(!MethodInfoMap.count(MD) &&
"Should not have method info for this method yet!");
@ -1737,6 +1799,11 @@ VtableBuilder::LayoutPrimaryAndSecondaryVtables(BaseSubobject Base,
VCallOffsets = Builder.getVCallOffsets();
}
// If we're laying out the most derived class we want to keep track of the
// virtual base class offset offsets.
if (Base.getBase() == MostDerivedClass)
VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
// Add the offset to top.
// FIXME: We should not use / 8 here.
int64_t OffsetToTop = -(int64_t)(OffsetInLayoutClass -
@ -1772,11 +1839,16 @@ VtableBuilder::LayoutPrimaryAndSecondaryVtables(BaseSubobject Base,
AddressPoints.insert(std::make_pair(PrimaryBase, AddressPoint));
}
bool BaseIsMorallyVirtual = BaseIsVirtual;
if (isBuildingConstructorVtable() && Base.getBase() == MostDerivedClass)
BaseIsMorallyVirtual = false;
// Layout secondary vtables.
LayoutSecondaryVtables(Base, OffsetInLayoutClass);
LayoutSecondaryVtables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
}
void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
bool BaseIsMorallyVirtual,
uint64_t OffsetInLayoutClass) {
// Itanium C++ ABI 2.5.2:
// Following the primary virtual table of a derived class are secondary
@ -1800,6 +1872,16 @@ void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
if (!BaseDecl->isDynamicClass())
continue;
if (isBuildingConstructorVtable()) {
// Itanium C++ ABI 2.6.4:
// Some of the base class subobjects may not need construction virtual
// tables, which will therefore not be present in the construction
// virtual table group, even though the subobject virtual tables are
// present in the main virtual table group for the complete object.
if (!BaseIsMorallyVirtual && !BaseDecl->getNumVBases())
continue;
}
// Get the base offset of this base.
uint64_t RelativeBaseOffset = Layout.getBaseClassOffset(BaseDecl);
uint64_t BaseOffset = Base.getBaseOffset() + RelativeBaseOffset;
@ -1810,7 +1892,7 @@ void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
// to emit secondary vtables for other bases of this base.
if (BaseDecl == PrimaryBase) {
LayoutSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset),
BaseOffsetInLayoutClass);
BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
continue;
}
@ -1920,15 +2002,15 @@ VtableBuilder::LayoutVtablesForVirtualBases(const CXXRecordDecl *RD,
/// dumpLayout - Dump the vtable layout.
void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
if (MostDerivedClass == LayoutClass) {
Out << "Vtable for '";
Out << MostDerivedClass->getQualifiedNameAsString();
} else {
if (isBuildingConstructorVtable()) {
Out << "Construction vtable for ('";
Out << MostDerivedClass->getQualifiedNameAsString() << "', ";
// FIXME: Don't use / 8 .
Out << MostDerivedClassOffset / 8 << ") in '";
Out << LayoutClass->getQualifiedNameAsString();
} else {
Out << "Vtable for '";
Out << MostDerivedClass->getQualifiedNameAsString();
}
Out << "' (" << Components.size() << " entries).\n";
@ -1945,8 +2027,6 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
AddressPointsByIndex.insert(std::make_pair(Index, Base));
}
unsigned NextReturnAdjustmentIndex = 0;
unsigned NextThisAdjustmentIndex = 0;
for (unsigned I = 0, E = Components.size(); I != E; ++I) {
uint64_t Index = I;
@ -1983,38 +2063,33 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
if (MD->isPure())
Out << " [pure]";
// If this function pointer has a return adjustment, dump it.
if (NextReturnAdjustmentIndex < ReturnAdjustments.size() &&
ReturnAdjustments[NextReturnAdjustmentIndex].first == I) {
const ReturnAdjustment Adjustment =
ReturnAdjustments[NextReturnAdjustmentIndex].second;
Out << "\n [return adjustment: ";
Out << Adjustment.NonVirtual << " non-virtual";
if (Adjustment.VBaseOffsetOffset)
Out << ", " << Adjustment.VBaseOffsetOffset << " vbase offset offset";
ThunkInfo Thunk = Thunks.lookup(I);
if (!Thunk.isEmpty()) {
// If this function pointer has a return adjustment, dump it.
if (!Thunk.Return.isEmpty()) {
Out << "\n [return adjustment: ";
Out << Thunk.Return.NonVirtual << " non-virtual";
if (Thunk.Return.VBaseOffsetOffset) {
Out << ", " << Thunk.Return.VBaseOffsetOffset;
Out << " vbase offset offset";
}
Out << ']';
Out << ']';
}
NextReturnAdjustmentIndex++;
}
// If this function pointer has a 'this' pointer adjustment, dump it.
if (NextThisAdjustmentIndex < ThisAdjustments.size() &&
ThisAdjustments[NextThisAdjustmentIndex].first == I) {
const ThisAdjustment Adjustment =
ThisAdjustments[NextThisAdjustmentIndex].second;
Out << "\n [this adjustment: ";
Out << Adjustment.NonVirtual << " non-virtual";
// If this function pointer has a 'this' pointer adjustment, dump it.
if (!Thunk.This.isEmpty()) {
Out << "\n [this adjustment: ";
Out << Thunk.This.NonVirtual << " non-virtual";
if (Thunk.This.VCallOffsetOffset) {
Out << ", " << Thunk.This.VCallOffsetOffset;
Out << " vcall offset offset";
}
if (Adjustment.VCallOffsetOffset)
Out << ", " << Adjustment.VCallOffsetOffset << " vcall offset offset";
Out << ']';
NextThisAdjustmentIndex++;
Out << ']';
}
}
break;
@ -2036,23 +2111,21 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
if (DD->isPure())
Out << " [pure]";
// If this destructor has a 'this' pointer adjustment, dump it.
if (NextThisAdjustmentIndex < ThisAdjustments.size() &&
ThisAdjustments[NextThisAdjustmentIndex].first == I) {
const ThisAdjustment Adjustment =
ThisAdjustments[NextThisAdjustmentIndex].second;
Out << "\n [this adjustment: ";
Out << Adjustment.NonVirtual << " non-virtual";
if (Adjustment.VCallOffsetOffset)
Out << ", " << Adjustment.VCallOffsetOffset << " vcall offset offset";
Out << ']';
NextThisAdjustmentIndex++;
}
ThunkInfo Thunk = Thunks.lookup(I);
if (!Thunk.isEmpty()) {
// If this destructor has a 'this' pointer adjustment, dump it.
if (!Thunk.This.isEmpty()) {
Out << "\n [this adjustment: ";
Out << Thunk.This.NonVirtual << " non-virtual";
if (Thunk.This.VCallOffsetOffset) {
Out << ", " << Thunk.This.VCallOffsetOffset;
Out << " vcall offset offset";
}
Out << ']';
}
}
break;
}
@ -2108,6 +2181,29 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
}
Out << '\n';
if (!isBuildingConstructorVtable() && MostDerivedClass->getNumVBases()) {
Out << "Virtual base offset offsets for '";
Out << MostDerivedClass->getQualifiedNameAsString() << "'.\n";
// We store the virtual base class names and their offsets in a map to get
// a stable order.
std::map<std::string, int64_t> ClassNamesAndOffsets;
for (VBaseOffsetOffsetsMapTy::const_iterator I = VBaseOffsetOffsets.begin(),
E = VBaseOffsetOffsets.end(); I != E; ++I) {
std::string ClassName = I->first->getQualifiedNameAsString();
int64_t OffsetOffset = I->second;
ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
}
for (std::map<std::string, int64_t>::const_iterator I =
ClassNamesAndOffsets.begin(), E = ClassNamesAndOffsets.end();
I != E; ++I)
Out << " " << I->first << " | " << I->second << '\n';
Out << "\n";
}
}
}
@ -2598,7 +2694,7 @@ class OldVtableBuilder {
CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
if (D != MostDerivedClass)
return CGM.getVtableInfo().getVirtualBaseOffsetIndex(D, B);
return CGM.getVtableInfo().getVirtualBaseOffsetOffset(D, B);
llvm::DenseMap<const CXXRecordDecl *, Index_t>::iterator i;
i = VBIndex.find(B);
if (i != VBIndex.end())
@ -3346,39 +3442,39 @@ CGVtableInfo::getAdjustments(GlobalDecl GD) {
return 0;
}
int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
const CXXRecordDecl *VBase) {
int64_t CGVtableInfo::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
const CXXRecordDecl *VBase) {
ClassPairTy ClassPair(RD, VBase);
VirtualBaseClassIndiciesTy::iterator I =
VirtualBaseClassIndicies.find(ClassPair);
if (I != VirtualBaseClassIndicies.end())
VirtualBaseClassOffsetOffsetsMapTy::iterator I =
VirtualBaseClassOffsetOffsets.find(ClassPair);
if (I != VirtualBaseClassOffsetOffsets.end())
return I->second;
// FIXME: This seems expensive. Can we do a partial job to get
// just this data.
AddressPointsMapTy AddressPoints;
OldVtableBuilder b(RD, RD, 0, CGM, false, AddressPoints);
D1(printf("vtable %s\n", RD->getNameAsCString()));
b.GenerateVtableForBase(RD);
b.GenerateVtableForVBases(RD);
VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/0,
BaseSubobject(RD, 0),
/*BaseIsVirtual=*/false,
/*OffsetInLayoutClass=*/0);
for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
b.getVBIndex().begin(), E = b.getVBIndex().end(); I != E; ++I) {
for (VCallAndVBaseOffsetBuilder::VBaseOffsetOffsetsMapTy::const_iterator I =
Builder.getVBaseOffsetOffsets().begin(),
E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) {
// Insert all types.
ClassPairTy ClassPair(RD, I->first);
VirtualBaseClassIndicies.insert(std::make_pair(ClassPair, I->second));
VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second));
}
I = VirtualBaseClassIndicies.find(ClassPair);
I = VirtualBaseClassOffsetOffsets.find(ClassPair);
// FIXME: The assertion below assertion currently fails with the old vtable
/// layout code if there is a non-virtual thunk adjustment in a vtable.
// Once the new layout is in place, this return should be removed.
if (I == VirtualBaseClassIndicies.end())
if (I == VirtualBaseClassOffsetOffsets.end())
return 0;
assert(I != VirtualBaseClassIndicies.end() && "Did not find index!");
assert(I != VirtualBaseClassOffsetOffsets.end() && "Did not find index!");
return I->second;
}
@ -3400,20 +3496,17 @@ CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
if (GenerateDefinition) {
if (LayoutClass == RD) {
assert(!IsVirtual &&
"Can't only have a virtual base in construction vtables!");
VtableBuilder Builder(*this, RD, Offset,
/*MostDerivedClassIsVirtual=*/false,
LayoutClass);
if (CGM.getLangOptions().DumpVtableLayouts)
Builder.dumpLayout(llvm::errs());
} else if (CGM.getLangOptions().DumpVtableLayouts) {
// We only build construction vtables when dumping vtable layouts for now.
VtableBuilder Builder(*this, RD, Offset,
/*MostDerivedClassIsVirtual=*/IsVirtual,
LayoutClass);
Builder.dumpLayout(llvm::errs());
"Can only have a virtual base in construction vtables!");
assert(!Offset &&
"Can only have a base offset in construction vtables!");
}
VtableBuilder Builder(*this, RD, Offset,
/*MostDerivedClassIsVirtual=*/IsVirtual,
LayoutClass);
if (CGM.getLangOptions().DumpVtableLayouts)
Builder.dumpLayout(llvm::errs());
}
llvm::SmallString<256> OutName;

View File

@ -149,10 +149,12 @@ class CGVtableInfo {
typedef std::pair<const CXXRecordDecl *,
const CXXRecordDecl *> ClassPairTy;
/// VirtualBaseClassIndicies - Contains the index into the vtable where the
/// offsets for virtual bases of a class are stored.
typedef llvm::DenseMap<ClassPairTy, int64_t> VirtualBaseClassIndiciesTy;
VirtualBaseClassIndiciesTy VirtualBaseClassIndicies;
/// VirtualBaseClassOffsetOffsets - Contains the vtable offset (relative to
/// the address point) in bytes where the offsets for virtual bases of a class
/// are stored.
typedef llvm::DenseMap<ClassPairTy, int64_t>
VirtualBaseClassOffsetOffsetsMapTy;
VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets;
/// Vtables - All the vtables which have been defined.
llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> Vtables;
@ -202,13 +204,13 @@ class CGVtableInfo {
/// stored.
uint64_t getMethodVtableIndex(GlobalDecl GD);
/// getVirtualBaseOffsetIndex - Return the index (relative to the vtable
/// address point) where the offset of the virtual base that contains the
/// given Base is stored, otherwise, if no virtual base contains the given
/// getVirtualBaseOffsetOffset - Return the offset in bytes (relative to the
/// vtable address point) where the offset of the virtual base that contains
/// the given base is stored, otherwise, if no virtual base contains the given
/// class, return 0. Base must be a virtual base class or an unambigious
/// base.
int64_t getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
const CXXRecordDecl *VBase);
int64_t getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
const CXXRecordDecl *VBase);
AdjustmentVectorTy *getAdjustments(GlobalDecl GD);

View File

@ -285,8 +285,7 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
break;
case TSK_ExplicitInstantiationDefinition:
// FIXME: explicit instantiation definitions should use weak linkage
return CodeGenModule::GVA_StrongExternal;
return CodeGenModule::GVA_ExplicitTemplateInstantiation;
case TSK_ExplicitInstantiationDeclaration:
case TSK_ImplicitInstantiation:
@ -343,6 +342,12 @@ CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
// merged with other definitions. c) C++ has the ODR, so we know the
// definition is dependable.
return llvm::Function::LinkOnceODRLinkage;
} else if (Linkage == GVA_ExplicitTemplateInstantiation) {
// An explicit instantiation of a template has weak linkage, since
// explicit instantiations can occur in multiple translation units
// and must all be equivalent. However, we are not allowed to
// throw away these explicit instantiations.
return llvm::Function::WeakODRLinkage;
} else {
assert(Linkage == GVA_StrongExternal);
// Otherwise, we have strong external linkage.
@ -589,6 +594,7 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
// static, static inline, always_inline, and extern inline functions can
// always be deferred. Normal inline functions can be deferred in C99/C++.
// Implicit template instantiations can also be deferred in C++.
if (Linkage == GVA_Internal || Linkage == GVA_C99Inline ||
Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
return true;
@ -1043,15 +1049,15 @@ GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
switch (TSK) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
// FIXME: ExplicitInstantiationDefinition should be weak!
case TSK_ExplicitInstantiationDefinition:
return CodeGenModule::GVA_StrongExternal;
case TSK_ExplicitInstantiationDeclaration:
llvm_unreachable("Variable should not be instantiated");
// Fall through to treat this like any other instantiation.
case TSK_ExplicitInstantiationDefinition:
return CodeGenModule::GVA_ExplicitTemplateInstantiation;
case TSK_ImplicitInstantiation:
return CodeGenModule::GVA_TemplateInstantiation;
}
@ -1171,7 +1177,10 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
GV->setLinkage(llvm::GlobalVariable::WeakODRLinkage);
else
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
} else if (Linkage == GVA_TemplateInstantiation)
} else if (Linkage == GVA_TemplateInstantiation ||
Linkage == GVA_ExplicitTemplateInstantiation)
// FIXME: It seems like we can provide more specific linkage here
// (LinkOnceODR, WeakODR).
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
else if (!getLangOptions().CPlusPlus && !CodeGenOpts.NoCommon &&
!D->hasExternalStorage() && !D->getInit() &&

View File

@ -437,7 +437,8 @@ class CodeGenModule : public BlockModule {
GVA_C99Inline,
GVA_CXXInline,
GVA_StrongExternal,
GVA_TemplateInstantiation
GVA_TemplateInstantiation,
GVA_ExplicitTemplateInstantiation
};
llvm::GlobalVariable::LinkageTypes

View File

@ -16,9 +16,9 @@ LEVEL = ../../../..
LIBRARYNAME := clangCodeGen
BUILD_ARCHIVE = 1
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
ifdef CLANG_VENDOR
CPPFLAGS += -DCLANG_VENDOR='"$(CLANG_VENDOR) "'
CPP.Flags += -DCLANG_VENDOR='"$(CLANG_VENDOR) "'
endif
include $(LEVEL)/Makefile.common

View File

@ -53,19 +53,19 @@ static const DeclContext *GetLocalClassFunctionDeclContext(
static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) {
assert((isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) &&
"Passed in decl is not a ctor or dtor!");
if (const TemplateDecl *TD = MD->getPrimaryTemplate()) {
MD = cast<CXXMethodDecl>(TD->getTemplatedDecl());
assert((isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) &&
"Templated decl is not a ctor or dtor!");
}
return MD;
}
static const unsigned UnknownArity = ~0U;
/// CXXNameMangler - Manage the mangling of a single name.
class CXXNameMangler {
MangleContext &Context;
@ -73,7 +73,7 @@ class CXXNameMangler {
const CXXMethodDecl *Structor;
unsigned StructorType;
llvm::DenseMap<uintptr_t, unsigned> Substitutions;
ASTContext &getASTContext() const { return Context.getASTContext(); }
@ -92,7 +92,7 @@ class CXXNameMangler {
~CXXNameMangler() {
if (Out.str()[0] == '\01')
return;
int status = 0;
char *result = abi::__cxa_demangle(Out.str().str().c_str(), 0, 0, &status);
assert(status == 0 && "Could not demangle mangled name!");
@ -151,7 +151,7 @@ class CXXNameMangler {
void mangleQualifiers(Qualifiers Quals);
void mangleObjCMethodName(const ObjCMethodDecl *MD);
// Declare manglers for every type class.
#define ABSTRACT_TYPE(CLASS, PARENT)
#define NON_CANONICAL_TYPE(CLASS, PARENT)
@ -172,10 +172,12 @@ class CXXNameMangler {
void mangleCXXCtorType(CXXCtorType T);
void mangleCXXDtorType(CXXDtorType T);
void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
void mangleTemplateArgs(const TemplateParameterList &PL,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
void mangleTemplateArgs(const TemplateArgumentList &L);
void mangleTemplateArg(const TemplateArgument &A);
void mangleTemplateArgs(const TemplateParameterList &PL,
const TemplateArgumentList &AL);
void mangleTemplateArg(const NamedDecl *P, const TemplateArgument &A);
void mangleTemplateParameter(unsigned Index);
};
@ -248,8 +250,10 @@ void CXXNameMangler::mangle(const NamedDecl *D, llvm::StringRef Prefix) {
Out << Prefix;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
mangleFunctionEncoding(FD);
else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
mangleName(VD);
else
mangleName(cast<VarDecl>(D));
mangleName(cast<FieldDecl>(D));
}
void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
@ -306,7 +310,7 @@ static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {
LinkageSpecDecl::lang_cxx && "Unexpected linkage decl!");
DC = DC->getParent();
}
return DC;
}
@ -315,10 +319,10 @@ static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {
static bool isStdNamespace(const DeclContext *DC) {
if (!DC->isNamespace())
return false;
if (!IgnoreLinkageSpecDecls(DC->getParent())->isTranslationUnit())
return false;
return isStd(cast<NamespaceDecl>(DC));
}
@ -349,12 +353,12 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) {
// ::= <local-name>
//
const DeclContext *DC = ND->getDeclContext();
if (GetLocalClassFunctionDeclContext(DC)) {
mangleLocalName(ND);
return;
}
// If this is an extern variable declared locally, the relevant DeclContext
// is that of the containing namespace, or the translation unit.
if (isa<FunctionDecl>(DC) && ND->hasLinkage())
@ -369,7 +373,8 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) {
const TemplateArgumentList *TemplateArgs = 0;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
mangleUnscopedTemplateName(TD);
mangleTemplateArgs(*TemplateArgs);
TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
mangleTemplateArgs(*TemplateParameters, *TemplateArgs);
return;
}
@ -391,7 +396,8 @@ void CXXNameMangler::mangleName(const TemplateDecl *TD,
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
mangleUnscopedTemplateName(TD);
mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
mangleTemplateArgs(*TemplateParameters, TemplateArgs, NumTemplateArgs);
} else {
mangleNestedName(TD, TemplateArgs, NumTemplateArgs);
}
@ -417,7 +423,7 @@ void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) {
= dyn_cast<TemplateTemplateParmDecl>(ND)) {
mangleTemplateParameter(TTP->getIndex());
return;
}
}
mangleUnscopedName(ND->getTemplatedDecl());
addSubstitution(ND);
@ -429,7 +435,7 @@ void CXXNameMangler::mangleNumber(int64_t Number) {
Out << 'n';
Number = -Number;
}
Out << Number;
}
@ -445,7 +451,7 @@ void CXXNameMangler::mangleCallOffset(const ThunkAdjustment &Adjustment) {
Out << '_';
return;
}
Out << 'v';
mangleNumber(Adjustment.NonVirtual);
Out << '_';
@ -496,7 +502,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
case DeclarationName::Identifier: {
if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
// We must avoid conflicts between internally- and externally-
// linked variable declaration names in the same TU.
// linked variable declaration names in the same TU.
// This naming convention is the same as that followed by GCC, though it
// shouldn't actually matter.
if (ND && isa<VarDecl>(ND) && ND->getLinkage() == InternalLinkage &&
@ -582,7 +588,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
unsigned Arity;
if (ND) {
Arity = cast<FunctionDecl>(ND)->getNumParams();
// If we have a C++ member function, we need to include the 'this' pointer.
// FIXME: This does not make sense for operators that are static, but their
// names stay the same regardless of the arity (operator new for instance).
@ -628,7 +634,8 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
const TemplateArgumentList *TemplateArgs = 0;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
mangleTemplatePrefix(TD);
mangleTemplateArgs(*TemplateArgs);
TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
mangleTemplateArgs(*TemplateParameters, *TemplateArgs);
}
else {
manglePrefix(DC, NoFunction);
@ -645,7 +652,8 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,
Out << 'N';
mangleTemplatePrefix(TD);
mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
mangleTemplateArgs(*TemplateParameters, TemplateArgs, NumTemplateArgs);
Out << 'E';
}
@ -656,26 +664,26 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {
// <discriminator> := _ <non-negative number>
const DeclContext *DC = ND->getDeclContext();
Out << 'Z';
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC))
mangleObjCMethodName(MD);
else if (const DeclContext *CDC = GetLocalClassFunctionDeclContext(DC)) {
mangleFunctionEncoding(cast<FunctionDecl>(CDC));
Out << 'E';
mangleNestedName(ND, DC, true /*NoFunction*/);
// FIXME. This still does not cover all cases.
unsigned disc;
if (Context.getNextDiscriminator(ND, disc)) {
if (disc < 10)
Out << '_' << disc;
else
else
Out << "__" << disc << '_';
}
return;
}
else
else
mangleFunctionEncoding(cast<FunctionDecl>(DC));
Out << 'E';
@ -702,7 +710,8 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
const TemplateArgumentList *TemplateArgs = 0;
if (const TemplateDecl *TD = isTemplate(cast<NamedDecl>(DC), TemplateArgs)) {
mangleTemplatePrefix(TD);
mangleTemplateArgs(*TemplateArgs);
TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
mangleTemplateArgs(*TemplateParameters, *TemplateArgs);
}
else if(NoFunction && isa<FunctionDecl>(DC))
return;
@ -729,7 +738,7 @@ void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) {
= dyn_cast<TemplateTemplateParmDecl>(ND)) {
mangleTemplateParameter(TTP->getIndex());
return;
}
}
manglePrefix(ND->getDeclContext());
mangleUnqualifiedName(ND->getTemplatedDecl());
@ -749,22 +758,22 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
case OO_Array_Delete: Out << "da"; break;
// ::= ps # + (unary)
// ::= pl # +
case OO_Plus:
case OO_Plus:
assert((Arity == 1 || Arity == 2) && "Invalid arity!");
Out << (Arity == 1? "ps" : "pl"); break;
// ::= ng # - (unary)
// ::= mi # -
case OO_Minus:
case OO_Minus:
assert((Arity == 1 || Arity == 2) && "Invalid arity!");
Out << (Arity == 1? "ng" : "mi"); break;
// ::= ad # & (unary)
// ::= an # &
case OO_Amp:
case OO_Amp:
assert((Arity == 1 || Arity == 2) && "Invalid arity!");
Out << (Arity == 1? "ad" : "an"); break;
// ::= de # * (unary)
// ::= ml # *
case OO_Star:
case OO_Star:
assert((Arity == 1 || Arity == 2) && "Invalid arity!");
Out << (Arity == 1? "de" : "ml"); break;
// ::= co # ~
@ -863,15 +872,15 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
llvm::SmallString<64> Name;
llvm::raw_svector_ostream OS(Name);
const ObjCContainerDecl *CD =
const ObjCContainerDecl *CD =
dyn_cast<ObjCContainerDecl>(MD->getDeclContext());
assert (CD && "Missing container decl in GetNameForMethod");
OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName();
if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD))
OS << '(' << CID->getNameAsString() << ')';
OS << ' ' << MD->getSelector().getAsString() << ']';
Out << OS.str().size() << OS.str();
}
@ -1143,7 +1152,9 @@ void CXXNameMangler::mangleType(const TypenameType *T) {
TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl();
assert(TD && "FIXME: Support dependent template names");
mangleTemplatePrefix(TD);
mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
mangleTemplateArgs(*TemplateParameters, TST->getArgs(),
TST->getNumArgs());
addSubstitution(QualType(TST, 0));
}
} else if (const TemplateTypeParmType *TTPT =
@ -1173,7 +1184,7 @@ void CXXNameMangler::mangleType(const TypeOfExprType *T) {
void CXXNameMangler::mangleType(const DecltypeType *T) {
Expr *E = T->getUnderlyingExpr();
// type ::= Dt <expression> E # decltype of an id-expression
// # or class member access
// ::= DT <expression> E # decltype of an expression
@ -1195,11 +1206,11 @@ void CXXNameMangler::mangleType(const DecltypeType *T) {
Out << 'E';
}
void CXXNameMangler::mangleIntegerLiteral(QualType T,
void CXXNameMangler::mangleIntegerLiteral(QualType T,
const llvm::APSInt &Value) {
// <expr-primary> ::= L <type> <value number> E # integer literal
Out << 'L';
mangleType(T);
if (T->isBooleanType()) {
// Boolean values are encoded as 0/1.
@ -1210,7 +1221,7 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T,
Value.abs().print(Out, false);
}
Out << 'E';
}
void CXXNameMangler::mangleCalledExpression(const Expr *E, unsigned Arity) {
@ -1314,7 +1325,7 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
break;
}
case Expr::CXXUnresolvedConstructExprClass: {
case Expr::CXXUnresolvedConstructExprClass: {
const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E);
unsigned N = CE->arg_size();
@ -1323,7 +1334,7 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
if (N != 1) Out << "_";
for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
if (N != 1) Out << "E";
break;
break;
}
case Expr::CXXTemporaryObjectExprClass:
@ -1355,18 +1366,18 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
case Expr::UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(E);
mangleOperatorName(UnaryOperator::getOverloadedOperator(UO->getOpcode()),
mangleOperatorName(UnaryOperator::getOverloadedOperator(UO->getOpcode()),
/*Arity=*/1);
mangleExpression(UO->getSubExpr());
break;
}
case Expr::BinaryOperatorClass: {
const BinaryOperator *BO = cast<BinaryOperator>(E);
mangleOperatorName(BinaryOperator::getOverloadedOperator(BO->getOpcode()),
mangleOperatorName(BinaryOperator::getOverloadedOperator(BO->getOpcode()),
/*Arity=*/2);
mangleExpression(BO->getLHS());
mangleExpression(BO->getRHS());
mangleExpression(BO->getRHS());
break;
}
@ -1396,7 +1407,7 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
mangleExpression(ECE->getSubExpr());
break;
}
case Expr::CXXOperatorCallExprClass: {
const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
unsigned NumArgs = CE->getNumArgs();
@ -1406,7 +1417,7 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
mangleExpression(CE->getArg(i));
break;
}
case Expr::ParenExprClass:
mangleExpression(cast<ParenExpr>(E)->getSubExpr());
break;
@ -1415,7 +1426,7 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl();
switch (D->getKind()) {
default:
default:
// <expr-primary> ::= L <mangled-name> E # external name
Out << 'L';
mangle(D, "_Z");
@ -1466,7 +1477,7 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
mangleType(FL->getType());
// TODO: avoid this copy with careful stream management.
llvm::SmallVector<char,20> Buffer;
llvm::SmallString<20> Buffer;
FL->getValue().bitcastToAPInt().toString(Buffer, 16, false);
Out.write(Buffer.data(), Buffer.size());
@ -1475,7 +1486,7 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
}
case Expr::IntegerLiteralClass:
mangleIntegerLiteral(E->getType(),
mangleIntegerLiteral(E->getType(),
llvm::APSInt(cast<IntegerLiteral>(E)->getValue()));
break;
@ -1521,24 +1532,27 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
}
}
void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentList &L) {
void CXXNameMangler::mangleTemplateArgs(const TemplateParameterList &PL,
const TemplateArgumentList &AL) {
// <template-args> ::= I <template-arg>+ E
Out << "I";
for (unsigned i = 0, e = L.size(); i != e; ++i)
mangleTemplateArg(L[i]);
for (unsigned i = 0, e = AL.size(); i != e; ++i)
mangleTemplateArg(PL.getParam(i), AL[i]);
Out << "E";
}
void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs,
void CXXNameMangler::mangleTemplateArgs(const TemplateParameterList &PL,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) {
// <template-args> ::= I <template-arg>+ E
Out << "I";
for (unsigned i = 0; i != NumTemplateArgs; ++i)
mangleTemplateArg(TemplateArgs[i]);
mangleTemplateArg(PL.getParam(i), TemplateArgs[i]);
Out << "E";
}
void CXXNameMangler::mangleTemplateArg(const TemplateArgument &A) {
void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
const TemplateArgument &A) {
// <template-arg> ::= <type> # type or template
// ::= X <expression> E # expression
// ::= <expr-primary> # simple expressions
@ -1554,7 +1568,7 @@ void CXXNameMangler::mangleTemplateArg(const TemplateArgument &A) {
assert(A.getAsTemplate().getAsTemplateDecl() &&
"FIXME: Support dependent template names");
mangleName(A.getAsTemplate().getAsTemplateDecl());
break;
break;
case TemplateArgument::Expression:
Out << 'X';
mangleExpression(A.getAsExpr());
@ -1566,18 +1580,33 @@ void CXXNameMangler::mangleTemplateArg(const TemplateArgument &A) {
case TemplateArgument::Declaration: {
// <expr-primary> ::= L <mangled-name> E # external name
// FIXME: Clang produces AST's where pointer-to-member-function expressions
// Clang produces AST's where pointer-to-member-function expressions
// and pointer-to-function expressions are represented as a declaration not
// an expression; this is not how gcc represents them and this changes the
// mangling.
// an expression. We compensate for it here to produce the correct mangling.
NamedDecl *D = cast<NamedDecl>(A.getAsDecl());
const NonTypeTemplateParmDecl *Parameter = cast<NonTypeTemplateParmDecl>(P);
bool compensateMangling = D->isCXXClassMember() &&
!Parameter->getType()->isReferenceType();
if (compensateMangling) {
Out << 'X';
mangleOperatorName(OO_Amp, 1);
}
Out << 'L';
// References to external entities use the mangled name; if the name would
// not normally be manged then mangle it as unqualified.
//
// FIXME: The ABI specifies that external names here should have _Z, but
// gcc leaves this off.
mangle(cast<NamedDecl>(A.getAsDecl()), "Z");
if (compensateMangling)
mangle(D, "_Z");
else
mangle(D, "Z");
Out << 'E';
if (compensateMangling)
Out << 'E';
break;
}
}
@ -1689,20 +1718,20 @@ bool isStreamCharSpecialization(const ClassTemplateSpecializationDecl *SD,
const char (&Str)[StrLen]) {
if (!SD->getIdentifier()->isStr(Str))
return false;
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
if (TemplateArgs.size() != 2)
return false;
if (!isCharType(TemplateArgs[0].getAsType()))
return false;
if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
return false;
return true;
}
bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
// <substitution> ::= St # ::std::
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
@ -1769,7 +1798,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
Out << "So";
return true;
}
// <substitution> ::= Sd # ::std::basic_iostream<char,
// ::std::char_traits<char> >
if (isStreamCharSpecialization(SD, "basic_iostream")) {
@ -1838,7 +1867,7 @@ void MangleContext::mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
/// \brief Mangles the a thunk with the offset n for the declaration D and
/// emits that name to the given output stream.
void MangleContext::mangleThunk(const FunctionDecl *FD,
void MangleContext::mangleThunk(const FunctionDecl *FD,
const ThunkAdjustment &ThisAdjustment,
llvm::SmallVectorImpl<char> &Res) {
assert(!isa<CXXDestructorDecl>(FD) &&
@ -1866,7 +1895,7 @@ void MangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *D,
/// \brief Mangles the a covariant thunk for the declaration D and emits that
/// name to the given output stream.
void
void
MangleContext::mangleCovariantThunk(const FunctionDecl *FD,
const CovariantThunkAdjustment& Adjustment,
llvm::SmallVectorImpl<char> &Res) {

View File

@ -268,16 +268,15 @@ llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty,
ASTContext &Context,
llvm::LLVMContext &VMContext) const {
if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
if (CodeGenFunction::hasAggregateLLVMType(Ty))
return ABIArgInfo::getIndirect(0);
} else {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType();
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType();
return (Ty->isPromotableIntegerType() ?
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
return (Ty->isPromotableIntegerType() ?
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
/// X86_32ABIInfo - The X86-32 ABI information.
@ -1367,6 +1366,8 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
// i8* reg_save_area;
// };
unsigned neededInt, neededSSE;
Ty = CGF.getContext().getCanonicalType(Ty);
ABIArgInfo AI = classifyArgumentType(Ty, CGF.getContext(), VMContext,
neededInt, neededSSE);
@ -1596,6 +1597,80 @@ llvm::Value *PIC16ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
}
// PowerPC-32
namespace {
class PPC32TargetCodeGenInfo : public DefaultTargetCodeGenInfo {
public:
int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const {
// This is recovered from gcc output.
return 1; // r1 is the dedicated stack pointer
}
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
llvm::Value *Address) const;
};
}
bool
PPC32TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
llvm::Value *Address) const {
// This is calculated from the LLVM and GCC tables and verified
// against gcc output. AFAIK all ABIs use the same encoding.
CodeGen::CGBuilderTy &Builder = CGF.Builder;
llvm::LLVMContext &Context = CGF.getLLVMContext();
const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context);
llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4);
llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8);
llvm::Value *Sixteen8 = llvm::ConstantInt::get(i8, 16);
// 0-31: r0-31, the 4-byte general-purpose registers
for (unsigned I = 0, E = 32; I != E; ++I) {
llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I);
Builder.CreateStore(Four8, Slot);
}
// 32-63: fp0-31, the 8-byte floating-point registers
for (unsigned I = 32, E = 64; I != E; ++I) {
llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I);
Builder.CreateStore(Eight8, Slot);
}
// 64-76 are various 4-byte special-purpose registers:
// 64: mq
// 65: lr
// 66: ctr
// 67: ap
// 68-75 cr0-7
// 76: xer
for (unsigned I = 64, E = 77; I != E; ++I) {
llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I);
Builder.CreateStore(Four8, Slot);
}
// 77-108: v0-31, the 16-byte vector registers
for (unsigned I = 77, E = 109; I != E; ++I) {
llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I);
Builder.CreateStore(Sixteen8, Slot);
}
// 109: vrsave
// 110: vscr
// 111: spe_acc
// 112: spefscr
// 113: sfp
for (unsigned I = 109, E = 114; I != E; ++I) {
llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I);
Builder.CreateStore(Four8, Slot);
}
return false;
}
// ARM ABI Implementation
namespace {
@ -2040,6 +2115,9 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() const {
case llvm::Triple::pic16:
return *(TheTargetCodeGenInfo = new PIC16TargetCodeGenInfo());
case llvm::Triple::ppc:
return *(TheTargetCodeGenInfo = new PPC32TargetCodeGenInfo());
case llvm::Triple::systemz:
return *(TheTargetCodeGenInfo = new SystemZTargetCodeGenInfo());

View File

@ -13,8 +13,10 @@
using namespace clang::driver;
Action::~Action() {
// FIXME: Free the inputs. The problem is that BindArchAction shares
// inputs; so we can't just walk the inputs.
if (OwnsInputs) {
for (iterator it = begin(), ie = end(); it != ie; ++it)
delete *it;
}
}
const char *Action::getClassName(ActionClass AC) {

View File

@ -80,9 +80,9 @@ Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
Arg *A1 = getLastArgNoClaim(Id1);
Arg *A2 = getLastArgNoClaim(Id2);
int A0Idx = A0 ? A0->getIndex() : -1;
int A1Idx = A1 ? A1->getIndex() : -1;
int A2Idx = A2 ? A2->getIndex() : -1;
int A0Idx = A0 ? (int) A0->getIndex() : -1;
int A1Idx = A1 ? (int) A1->getIndex() : -1;
int A2Idx = A2 ? (int) A2->getIndex() : -1;
if (A0Idx > A1Idx) {
if (A0Idx > A2Idx)
@ -218,23 +218,30 @@ const char *DerivedArgList::MakeArgString(llvm::StringRef Str) const {
}
Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option *Opt) const {
return new FlagArg(Opt, BaseArgs.MakeIndex(Opt->getName()), BaseArg);
Arg *A = new FlagArg(Opt, BaseArgs.MakeIndex(Opt->getName()), BaseArg);
SynthesizedArgs.push_back(A);
return A;
}
Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt,
llvm::StringRef Value) const {
return new PositionalArg(Opt, BaseArgs.MakeIndex(Value), BaseArg);
Arg *A = new PositionalArg(Opt, BaseArgs.MakeIndex(Value), BaseArg);
SynthesizedArgs.push_back(A);
return A;
}
Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt,
llvm::StringRef Value) const {
return new SeparateArg(Opt, BaseArgs.MakeIndex(Opt->getName(), Value), 1,
BaseArg);
Arg *A = new SeparateArg(Opt, BaseArgs.MakeIndex(Opt->getName(), Value), 1,
BaseArg);
SynthesizedArgs.push_back(A);
return A;
}
Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option *Opt,
llvm::StringRef Value) const {
std::string Joined(Opt->getName());
Joined += Value;
return new JoinedArg(Opt, BaseArgs.MakeIndex(Joined.c_str()), BaseArg);
Arg *A = new JoinedArg(Opt, BaseArgs.MakeIndex(Opt->getName() + Value.str()),
BaseArg);
SynthesizedArgs.push_back(A);
return A;
}

View File

@ -503,8 +503,11 @@ void Driver::BuildUniversalActions(const ArgList &Args,
<< types::getTypeName(Act->getType());
ActionList Inputs;
for (unsigned i = 0, e = Archs.size(); i != e; ++i)
for (unsigned i = 0, e = Archs.size(); i != e; ++i) {
Inputs.push_back(new BindArchAction(Act, Archs[i]));
if (i != 0)
Inputs.back()->setOwnsInputs(false);
}
// Lipo if necessary, we do it this way because we need to set the arch flag
// so that -Xarch_ gets overwritten.

View File

@ -23,8 +23,18 @@ Command::Command(const Action &_Source, const Tool &_Creator,
PipedJob::PipedJob() : Job(PipedJobClass) {}
PipedJob::~PipedJob() {
for (iterator it = begin(), ie = end(); it != ie; ++it)
delete *it;
}
JobList::JobList() : Job(JobListClass) {}
JobList::~JobList() {
for (iterator it = begin(), ie = end(); it != ie; ++it)
delete *it;
}
void Job::addCommand(Command *C) {
if (PipedJob *PJ = dyn_cast<PipedJob>(this))
PJ->addCommand(C);

View File

@ -35,8 +35,9 @@
#include "llvm/System/Path.h"
using namespace clang;
ASTUnit::ASTUnit(bool _MainFileIsAST)
: MainFileIsAST(_MainFileIsAST), ConcurrencyCheckValue(CheckUnlocked) {
ASTUnit::ASTUnit(Diagnostic &Diag, bool _MainFileIsAST)
: SourceMgr(Diag), MainFileIsAST(_MainFileIsAST),
ConcurrencyCheckValue(CheckUnlocked) {
}
ASTUnit::~ASTUnit() {
ConcurrencyCheckValue = CheckLocked;
@ -146,7 +147,7 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
RemappedFile *RemappedFiles,
unsigned NumRemappedFiles,
bool CaptureDiagnostics) {
llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
llvm::OwningPtr<ASTUnit> AST(new ASTUnit(Diags, true));
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
@ -311,7 +312,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
"FIXME: AST inputs not yet supported here!");
// Create the AST unit.
AST.reset(new ASTUnit(false));
AST.reset(new ASTUnit(Diags, false));
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;

View File

@ -196,6 +196,11 @@ class PTHWriter {
Out.write(Ptr, NumBytes);
}
void EmitString(llvm::StringRef V) {
::Emit16(Out, V.size());
EmitBuf(V.data(), V.size());
}
/// EmitIdentifierTable - Emits two tables to the PTH file. The first is
/// a hashtable mapping from identifier strings to persistent IDs.
/// The second is a straight table mapping from persistent IDs to string data
@ -214,7 +219,7 @@ class PTHWriter {
: Out(out), PP(pp), idcount(0), CurStrOffset(0) {}
PTHMap &getPM() { return PM; }
void GeneratePTH(const std::string *MainFile = 0);
void GeneratePTH(const std::string &MainFile);
};
} // end anonymous namespace
@ -295,7 +300,7 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) {
}
if (Tok.is(tok::identifier)) {
Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
PP.LookUpIdentifierInfo(Tok);
EmitToken(Tok);
continue;
}
@ -321,7 +326,6 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) {
}
IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok);
Tok.setIdentifierInfo(II);
tok::PPKeywordKind K = II->getPPKeywordID();
ParsingPreprocessorDirective = true;
@ -344,7 +348,7 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) {
L.setParsingPreprocessorDirective(false);
assert(!Tok.isAtStartOfLine());
if (Tok.is(tok::identifier))
Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
PP.LookUpIdentifierInfo(Tok);
break;
}
@ -436,7 +440,7 @@ Offset PTHWriter::EmitCachedSpellings() {
return SpellingsOff;
}
void PTHWriter::GeneratePTH(const std::string *MainFile) {
void PTHWriter::GeneratePTH(const std::string &MainFile) {
// Generate the prologue.
Out << "cfe-pth";
Emit32(PTHManager::Version);
@ -447,9 +451,8 @@ void PTHWriter::GeneratePTH(const std::string *MainFile) {
Emit32(0);
// Write the name of the MainFile.
if (MainFile && !MainFile->empty()) {
Emit16(MainFile->length());
EmitBuf(MainFile->data(), MainFile->length());
if (!MainFile.empty()) {
EmitString(MainFile);
} else {
// String with 0 bytes.
Emit16(0);
@ -471,7 +474,7 @@ void PTHWriter::GeneratePTH(const std::string *MainFile) {
if (!P.isAbsolute())
continue;
const llvm::MemoryBuffer *B = C.getBuffer();
const llvm::MemoryBuffer *B = C.getBuffer(PP.getDiagnostics());
if (!B) continue;
FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User);
@ -533,15 +536,8 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {
const SourceManager &SrcMgr = PP.getSourceManager();
const FileEntry *MainFile = SrcMgr.getFileEntryForID(SrcMgr.getMainFileID());
llvm::sys::Path MainFilePath(MainFile->getName());
std::string MainFileName;
if (!MainFilePath.isAbsolute()) {
llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
P.appendComponent(MainFilePath.str());
MainFileName = P.str();
} else {
MainFileName = MainFilePath.str();
}
MainFilePath.makeAbsolute();
// Create the PTHWriter.
PTHWriter PW(*OS, PP);
@ -558,18 +554,18 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {
// Generate the PTH file.
PP.getFileManager().removeStatCache(StatCache);
PW.GeneratePTH(&MainFileName);
PW.GeneratePTH(MainFilePath.str());
}
//===----------------------------------------------------------------------===//
namespace {
class PTHIdKey {
public:
const IdentifierInfo* II;
uint32_t FileOffset;
};
namespace {
class PTHIdentifierTableTrait {
public:
typedef PTHIdKey* key_type;

View File

@ -185,7 +185,7 @@ void CompilerInstance::createFileManager() {
// Source Manager
void CompilerInstance::createSourceManager() {
SourceMgr.reset(new SourceManager());
SourceMgr.reset(new SourceManager(getDiagnostics()));
}
// Preprocessor
@ -294,6 +294,8 @@ void CompilerInstance::createCodeCompletionConsumer() {
getFrontendOpts().DebugCodeCompletionPrinter,
getFrontendOpts().ShowMacrosInCodeCompletion,
llvm::outs()));
if (!CompletionConsumer)
return;
if (CompletionConsumer->isOutputBinary() &&
llvm::sys::Program::ChangeStdoutToBinary()) {

View File

@ -474,6 +474,8 @@ static void LangOptsToArgs(const LangOptions &Opts,
Res.push_back("-fcatch-undefined-behavior");
if (Opts.WritableStrings)
Res.push_back("-fwritable-strings");
if (Opts.ConstStrings)
Res.push_back("-Wwrite-strings");
if (!Opts.LaxVectorConversions)
Res.push_back("-fno-lax-vector-conversions");
if (Opts.AltiVec)
@ -1162,6 +1164,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings);
Opts.Microsoft = Args.hasArg(OPT_fms_extensions);
Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings);
Opts.ConstStrings = Args.hasArg(OPT_Wwrite_strings);
if (Args.hasArg(OPT_fno_lax_vector_conversions))
Opts.LaxVectorConversions = 0;
if (Args.hasArg(OPT_fno_threadsafe_statics))

View File

@ -40,13 +40,13 @@ class HTMLDiagnostics : public PathDiagnosticClient {
std::vector<const PathDiagnostic*> BatchedDiags;
public:
HTMLDiagnostics(const std::string& prefix, const Preprocessor &pp);
virtual ~HTMLDiagnostics() { FlushDiagnostics(NULL); }
virtual void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade);
virtual void HandlePathDiagnostic(const PathDiagnostic* D);
virtual llvm::StringRef getName() const {
return "HTMLDiagnostics";
}
@ -108,7 +108,7 @@ HTMLDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade)
ReportDiag(*D, FilesMade);
delete D;
}
BatchedDiags.clear();
}
@ -294,7 +294,7 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
llvm::raw_fd_ostream os(H.c_str(), ErrorMsg);
if (!ErrorMsg.empty()) {
(llvm::errs() << "warning: could not create file '" << F.str()
(llvm::errs() << "warning: could not create file '" << F.str()
<< "'\n").flush();
return;
}
@ -439,10 +439,10 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
{
FullSourceLoc L = MP->getLocation().asLocation().getInstantiationLoc();
assert(L.isFileID());
std::pair<const char*, const char*> BufferInfo = L.getBufferData();
const char* MacroName = L.getDecomposedLoc().second + BufferInfo.first;
Lexer rawLexer(L, PP.getLangOptions(), BufferInfo.first,
MacroName, BufferInfo.second);
llvm::StringRef BufferInfo = L.getBufferData();
const char* MacroName = L.getDecomposedLoc().second + BufferInfo.data();
Lexer rawLexer(L, PP.getLangOptions(), BufferInfo.begin(),
MacroName, BufferInfo.end());
Token TheTok;
rawLexer.LexFromRawLexer(TheTok);
@ -502,19 +502,13 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
}
static void EmitAlphaCounter(llvm::raw_ostream& os, unsigned n) {
llvm::SmallVector<char, 10> buf;
unsigned x = n % ('z' - 'a');
n /= 'z' - 'a';
do {
unsigned x = n % ('z' - 'a');
buf.push_back('a' + x);
n = n / ('z' - 'a');
} while (n);
if (n > 0)
EmitAlphaCounter(os, n);
assert(!buf.empty());
for (llvm::SmallVectorImpl<char>::reverse_iterator I=buf.rbegin(),
E=buf.rend(); I!=E; ++I)
os << *I;
os << char('a' + x);
}
unsigned HTMLDiagnostics::ProcessMacroPiece(llvm::raw_ostream& os,

View File

@ -11,7 +11,7 @@ LEVEL = ../../../..
LIBRARYNAME := clangFrontend
BUILD_ARCHIVE = 1
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
include $(LEVEL)/Makefile.common

View File

@ -2628,7 +2628,7 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
unsigned StrLen = (((unsigned) StrLenPtr[0])
| (((unsigned) StrLenPtr[1]) << 8)) - 1;
IdentifiersLoaded[ID - 1]
= &PP->getIdentifierTable().get(Str, Str + StrLen);
= &PP->getIdentifierTable().get(Str, StrLen);
}
return IdentifiersLoaded[ID - 1];

View File

@ -131,10 +131,11 @@ void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
TD->setDefinition(Record[Idx++]);
TD->setEmbeddedInDeclarator(Record[Idx++]);
TD->setTypedefForAnonDecl(
cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++])));
TD->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
TD->setTagKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
// FIXME: maybe read optional qualifier and its range.
TD->setTypedefForAnonDecl(
cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++])));
}
void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) {
@ -168,6 +169,7 @@ void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
TypeSourceInfo *TInfo = Reader.GetTypeSourceInfo(Record, Idx);
if (TInfo)
DD->setTypeSourceInfo(TInfo);
// FIXME: read optional qualifier and its range.
}
void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
@ -411,6 +413,7 @@ void PCHDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) {
void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
VisitVarDecl(PD);
PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
PD->setHasInheritedDefaultArg(Record[Idx++]);
}
void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {

View File

@ -565,7 +565,7 @@ void PCHWriter::WriteBlockInfoBlock() {
RECORD(EXT_VECTOR_DECLS);
RECORD(COMMENT_RANGES);
RECORD(VERSION_CONTROL_BRANCH_REVISION);
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
RECORD(SM_SLOC_FILE_ENTRY);
@ -710,24 +710,17 @@ void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) {
unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev);
llvm::sys::Path MainFilePath(MainFile->getName());
std::string MainFileName;
if (!MainFilePath.isAbsolute()) {
llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
P.appendComponent(MainFilePath.str());
MainFileName = P.str();
} else {
MainFileName = MainFilePath.str();
}
MainFilePath.makeAbsolute();
const char *MainFileNameStr = MainFileName.c_str();
const char *MainFileNameStr = MainFilePath.c_str();
MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr,
isysroot);
RecordData Record;
Record.push_back(pch::ORIGINAL_FILE_NAME);
Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr);
}
// Repository branch/version information.
BitCodeAbbrev *RepoAbbrev = new BitCodeAbbrev();
RepoAbbrev->Add(BitCodeAbbrevOp(pch::VERSION_CONTROL_BRANCH_REVISION));
@ -758,9 +751,9 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
Record.push_back(LangOpts.ObjC1); // Objective-C 1 support enabled.
Record.push_back(LangOpts.ObjC2); // Objective-C 2 support enabled.
Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C
Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C
// modern abi enabled.
Record.push_back(LangOpts.ObjCNonFragileABI2); // Objective-C enhanced
Record.push_back(LangOpts.ObjCNonFragileABI2); // Objective-C enhanced
// modern abi enabled.
Record.push_back(LangOpts.PascalStrings); // Allow Pascal strings
@ -1048,7 +1041,7 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
for (unsigned I = 1, N = SourceMgr.sloc_entry_size(); I != N; ++I) {
// Get this source location entry.
const SrcMgr::SLocEntry *SLoc = &SourceMgr.getSLocEntry(I);
// Record the offset of this source-location entry.
SLocEntryOffsets.push_back(Stream.GetCurrentBitNo());
@ -1079,13 +1072,8 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
// Turn the file name into an absolute path, if it isn't already.
const char *Filename = Content->Entry->getName();
llvm::sys::Path FilePath(Filename, strlen(Filename));
std::string FilenameStr;
if (!FilePath.isAbsolute()) {
llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
P.appendComponent(FilePath.str());
FilenameStr = P.str();
Filename = FilenameStr.c_str();
}
FilePath.makeAbsolute();
Filename = FilePath.c_str();
Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename);
@ -1101,7 +1089,8 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
// We add one to the size so that we capture the trailing NULL
// that is required by llvm::MemoryBuffer::getMemBuffer (on
// the reader side).
const llvm::MemoryBuffer *Buffer = Content->getBuffer();
const llvm::MemoryBuffer *Buffer
= Content->getBuffer(PP.getDiagnostics());
const char *Name = Buffer->getBufferIdentifier();
Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record,
llvm::StringRef(Name, strlen(Name) + 1));
@ -1998,9 +1987,9 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
// Build a record containing all of the static unused functions in this file.
RecordData UnusedStaticFuncs;
for (unsigned i=0, e = SemaRef.UnusedStaticFuncs.size(); i !=e; ++i)
for (unsigned i=0, e = SemaRef.UnusedStaticFuncs.size(); i !=e; ++i)
AddDeclRef(SemaRef.UnusedStaticFuncs[i], UnusedStaticFuncs);
// Build a record containing all of the locally-scoped external
// declarations in this header file. Generally, this record will be
// empty.
@ -2063,7 +2052,7 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
WriteDecl(Context, DOT.getDecl());
}
Stream.ExitBlock();
WritePreprocessor(PP);
WriteMethodPool(SemaRef);
WriteIdentifierTable(PP);
@ -2105,7 +2094,7 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
// Write the record containing unused static functions.
if (!UnusedStaticFuncs.empty())
Stream.EmitRecord(pch::UNUSED_STATIC_FUNCS, UnusedStaticFuncs);
// Write the record containing locally-scoped external definitions.
if (!LocallyScopedExternalDecls.empty())
Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS,
@ -2206,7 +2195,7 @@ void PCHWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record) {
AddTypeRef(TInfo->getType(), Record);
TypeLocWriter TLW(*this, Record);
for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
TLW.Visit(TL);
TLW.Visit(TL);
}
void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
@ -2227,14 +2216,14 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
ID = NextTypeID++;
DeclTypesToEmit.push(T);
}
// Encode the type qualifiers in the type reference.
Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
return;
}
assert(!T.hasLocalQualifiers());
if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
pch::TypeID ID = 0;
switch (BT->getKind()) {

View File

@ -127,9 +127,10 @@ void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
Record.push_back(D->isDefinition());
Record.push_back(D->isEmbeddedInDeclarator());
Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);
Writer.AddSourceLocation(D->getRBraceLoc(), Record);
Writer.AddSourceLocation(D->getTagKeywordLoc(), Record);
// FIXME: maybe write optional qualifier and its range.
Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);
}
void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) {
@ -165,6 +166,7 @@ void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
VisitValueDecl(D);
Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
// FIXME: write optional qualifier and its range.
}
void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
@ -398,6 +400,7 @@ void PCHDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
VisitVarDecl(D);
Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding
Record.push_back(D->hasInheritedDefaultArg());
Code = pch::DECL_PARM_VAR;
@ -412,7 +415,8 @@ void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
D->getPCHLevel() == 0 &&
D->getStorageClass() == 0 &&
!D->hasCXXDirectInitializer() && // Can params have this ever?
D->getObjCDeclQualifier() == 0)
D->getObjCDeclQualifier() == 0 &&
!D->hasInheritedDefaultArg())
AbbrevToUse = Writer.getParmVarDeclAbbrev();
// Check things we know are true of *every* PARM_VAR_DECL, which is more than
@ -496,6 +500,7 @@ void PCHWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // HasInit
// ParmVarDecl
Abv->Add(BitCodeAbbrevOp(0)); // ObjCDeclQualifier
Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedDefaultArg
ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv);
}

View File

@ -61,7 +61,7 @@ static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI,
if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace())
OS << ' ';
llvm::SmallVector<char, 128> SpellingBuffer;
llvm::SmallString<128> SpellingBuffer;
for (MacroInfo::tokens_iterator I = MI.tokens_begin(), E = MI.tokens_end();
I != E; ++I) {
if (I->hasLeadingSpace())

View File

@ -79,7 +79,7 @@ static void LexRawTokensFromMainFile(Preprocessor &PP,
// up the indentifier info. This is important for equality comparison of
// identifier tokens.
if (RawTok.is(tok::identifier) && !RawTok.getIdentifierInfo())
RawTok.setIdentifierInfo(PP.LookUpIdentifierInfo(RawTok));
PP.LookUpIdentifierInfo(RawTok);
RawTokens.push_back(RawTok);
} while (RawTok.isNot(tok::eof));

View File

@ -89,6 +89,7 @@ namespace {
FunctionDecl *MsgSendFpretFunctionDecl;
FunctionDecl *GetClassFunctionDecl;
FunctionDecl *GetMetaClassFunctionDecl;
FunctionDecl *GetSuperClassFunctionDecl;
FunctionDecl *SelGetUidFunctionDecl;
FunctionDecl *CFStringFunctionDecl;
FunctionDecl *SuperContructorFunctionDecl;
@ -133,7 +134,8 @@ namespace {
llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
// This maps a property to it's assignment statement.
@ -271,7 +273,7 @@ namespace {
void RewriteTypeOfDecl(VarDecl *VD);
void RewriteObjCQualifiedInterfaceTypes(Expr *E);
bool needToScanForQualifiers(QualType T);
ObjCInterfaceDecl *isSuperReceiver(Expr *recExpr);
bool isSuperReceiver(Expr *recExpr);
QualType getSuperStructType();
QualType getConstantStringStructType();
bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
@ -323,6 +325,7 @@ namespace {
void SynthMsgSendSuperStretFunctionDecl();
void SynthGetClassFunctionDecl();
void SynthGetMetaClassFunctionDecl();
void SynthGetSuperClassFunctionDecl();
void SynthSelGetUidFunctionDecl();
void SynthSuperContructorFunctionDecl();
@ -370,6 +373,7 @@ namespace {
void RewriteByRefVar(VarDecl *VD);
std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
Stmt *RewriteBlockDeclRefExpr(Expr *VD);
Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
@ -510,6 +514,7 @@ void RewriteObjC::Initialize(ASTContext &context) {
MsgSendFpretFunctionDecl = 0;
GetClassFunctionDecl = 0;
GetMetaClassFunctionDecl = 0;
GetSuperClassFunctionDecl = 0;
SelGetUidFunctionDecl = 0;
CFStringFunctionDecl = 0;
ConstantStringClassReference = 0;
@ -572,6 +577,8 @@ void RewriteObjC::Initialize(ASTContext &context) {
Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
Preamble += "(const char *);\n";
Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
Preamble += "(struct objc_class *);\n";
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
Preamble += "(const char *);\n";
Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
@ -699,9 +706,9 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
void RewriteObjC::RewriteInclude() {
SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
const char *MainBufStart = MainBuf.first;
const char *MainBufEnd = MainBuf.second;
llvm::StringRef MainBuf = SM->getBufferData(MainFileID);
const char *MainBufStart = MainBuf.begin();
const char *MainBufEnd = MainBuf.end();
size_t ImportLen = strlen("import");
// Loop over the whole file, looking for includes.
@ -724,9 +731,9 @@ void RewriteObjC::RewriteInclude() {
}
void RewriteObjC::RewriteTabs() {
std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
const char *MainBufStart = MainBuf.first;
const char *MainBufEnd = MainBuf.second;
llvm::StringRef MainBuf = SM->getBufferData(MainFileID);
const char *MainBufStart = MainBuf.begin();
const char *MainBufEnd = MainBuf.end();
// Loop over the whole file, looking for tabs.
for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
@ -966,8 +973,6 @@ void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
}
void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
SourceLocation LocStart = PDecl->getLocStart();
// FIXME: handle protocol headers that are declared across multiple lines.
@ -2491,6 +2496,23 @@ void RewriteObjC::SynthGetClassFunctionDecl() {
FunctionDecl::Extern, false);
}
// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
void RewriteObjC::SynthGetSuperClassFunctionDecl() {
IdentifierInfo *getSuperClassIdent =
&Context->Idents.get("class_getSuperclass");
llvm::SmallVector<QualType, 16> ArgTys;
ArgTys.push_back(Context->getObjCClassType());
QualType getClassType = Context->getFunctionType(Context->getObjCClassType(),
&ArgTys[0], ArgTys.size(),
false /*isVariadic*/, 0,
false, false, 0, 0, false,
CC_Default);
GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
getSuperClassIdent, getClassType, 0,
FunctionDecl::Extern, false);
}
// SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name);
void RewriteObjC::SynthGetMetaClassFunctionDecl() {
IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
@ -2551,18 +2573,10 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
return cast;
}
ObjCInterfaceDecl *RewriteObjC::isSuperReceiver(Expr *recExpr) {
bool RewriteObjC::isSuperReceiver(Expr *recExpr) {
// check if we are sending a message to 'super'
if (!CurMethodDef || !CurMethodDef->isInstanceMethod()) return 0;
if (ObjCSuperExpr *Super = dyn_cast<ObjCSuperExpr>(recExpr)) {
const ObjCObjectPointerType *OPT =
Super->getType()->getAs<ObjCObjectPointerType>();
assert(OPT);
const ObjCInterfaceType *IT = OPT->getInterfaceType();
return IT->getDecl();
}
return 0;
if (!CurMethodDef || !CurMethodDef->isInstanceMethod()) return false;
return isa<ObjCSuperExpr>(recExpr);
}
// struct objc_super { struct objc_object *receiver; struct objc_class *super; };
@ -2640,6 +2654,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SynthMsgSendFpretFunctionDecl();
if (!GetClassFunctionDecl)
SynthGetClassFunctionDecl();
if (!GetSuperClassFunctionDecl)
SynthGetSuperClassFunctionDecl();
if (!GetMetaClassFunctionDecl)
SynthGetMetaClassFunctionDecl();
@ -2669,8 +2685,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
ObjCInterfaceDecl *SuperDecl =
CurMethodDef->getClassInterface()->getSuperClass();
ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
llvm::SmallVector<Expr*, 4> InitExprs;
@ -2683,19 +2698,31 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SourceLocation()))
); // set the 'receiver'.
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
llvm::SmallVector<Expr*, 8> ClsExprs;
QualType argType = Context->getPointerType(Context->CharTy);
ClsExprs.push_back(StringLiteral::Create(*Context,
SuperDecl->getIdentifier()->getNameStart(),
SuperDecl->getIdentifier()->getLength(),
ClassDecl->getIdentifier()->getNameStart(),
ClassDecl->getIdentifier()->getLength(),
false, argType, SourceLocation()));
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
&ClsExprs[0],
ClsExprs.size(),
StartLoc,
EndLoc);
// (Class)objc_getClass("CurrentClass")
CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
Context->getObjCClassType(),
CastExpr::CK_Unknown, Cls);
ClsExprs.clear();
ClsExprs.push_back(ArgExpr);
Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
&ClsExprs[0], ClsExprs.size(),
StartLoc, EndLoc);
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
// To turn off a warning, type-cast to 'id'
InitExprs.push_back( // set 'super class', using objc_getClass().
InitExprs.push_back( // set 'super class', using class_getSuperclass().
NoTypeInfoCStyleCastExpr(Context,
Context->getObjCIdType(),
CastExpr::CK_Unknown, Cls));
@ -2755,12 +2782,12 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
} else { // instance message.
Expr *recExpr = Exp->getReceiver();
if (ObjCInterfaceDecl *SuperDecl = isSuperReceiver(recExpr)) {
if (isSuperReceiver(recExpr)) {
MsgSendFlavor = MsgSendSuperFunctionDecl;
if (MsgSendStretFlavor)
MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
llvm::SmallVector<Expr*, 4> InitExprs;
InitExprs.push_back(
@ -2770,20 +2797,32 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
Context->getObjCIdType(),
SourceLocation()))
); // set the 'receiver'.
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
llvm::SmallVector<Expr*, 8> ClsExprs;
QualType argType = Context->getPointerType(Context->CharTy);
ClsExprs.push_back(StringLiteral::Create(*Context,
SuperDecl->getIdentifier()->getNameStart(),
SuperDecl->getIdentifier()->getLength(),
ClassDecl->getIdentifier()->getNameStart(),
ClassDecl->getIdentifier()->getLength(),
false, argType, SourceLocation()));
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
&ClsExprs[0],
ClsExprs.size(),
StartLoc, EndLoc);
// (Class)objc_getClass("CurrentClass")
CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
Context->getObjCClassType(),
CastExpr::CK_Unknown, Cls);
ClsExprs.clear();
ClsExprs.push_back(ArgExpr);
Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
&ClsExprs[0], ClsExprs.size(),
StartLoc, EndLoc);
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
// To turn off a warning, type-cast to 'id'
InitExprs.push_back(
// set 'super class', using objc_getClass().
// set 'super class', using class_getSuperclass().
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
CastExpr::CK_Unknown, Cls));
// struct objc_super
@ -3986,6 +4025,12 @@ void RewriteObjC::RewriteByRefString(std::string &ResultStr,
"_" + utostr(BlockByRefDeclNo[VD]) ;
}
static bool HasLocalVariableExternalStorage(ValueDecl *VD) {
if (VarDecl *Var = dyn_cast<VarDecl>(VD))
return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
return false;
}
std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
const char *funcName,
std::string Tag) {
@ -4060,7 +4105,10 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
}
else {
std::string Name = (*I)->getNameAsString();
(*I)->getType().getAsStringInternal(Name, Context->PrintingPolicy);
QualType QT = (*I)->getType();
if (HasLocalVariableExternalStorage(*I))
QT = Context->getPointerType(QT);
QT.getAsStringInternal(Name, Context->PrintingPolicy);
S += Name + " = __cself->" +
(*I)->getNameAsString() + "; // bound by copy\n";
}
@ -4149,8 +4197,11 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
S += "struct __block_impl *";
Constructor += ", void *" + ArgName;
} else {
(*I)->getType().getAsStringInternal(FieldName, Context->PrintingPolicy);
(*I)->getType().getAsStringInternal(ArgName, Context->PrintingPolicy);
QualType QT = (*I)->getType();
if (HasLocalVariableExternalStorage(*I))
QT = Context->getPointerType(QT);
QT.getAsStringInternal(FieldName, Context->PrintingPolicy);
QT.getAsStringInternal(ArgName, Context->PrintingPolicy);
Constructor += ", " + ArgName;
}
S += FieldName + ";\n";
@ -4380,10 +4431,19 @@ void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
GetBlockDeclRefExprs(*CI);
}
// Handle specific things.
if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) {
// FIXME: Handle enums.
if (!isa<FunctionDecl>(CDRE->getDecl()))
BlockDeclRefs.push_back(CDRE);
}
else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
if (HasLocalVariableExternalStorage(DRE->getDecl())) {
BlockDeclRefExpr *BDRE =
new (Context)BlockDeclRefExpr(DRE->getDecl(), DRE->getType(),
DRE->getLocation(), false);
BlockDeclRefs.push_back(BDRE);
}
return;
}
@ -4406,10 +4466,16 @@ void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,
}
// Handle specific things.
if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) {
if (!isa<FunctionDecl>(CDRE->getDecl()) &&
!InnerContexts.count(CDRE->getDecl()->getDeclContext()))
InnerBlockDeclRefs.push_back(CDRE);
}
else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl()))
if (Var->isFunctionOrMethodVarDecl())
ImportedLocalExternalDecls.insert(Var);
}
return;
}
@ -4572,6 +4638,23 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) {
return PE;
}
// Rewrites the imported local variable V with external storage
// (static, extern, etc.) as *V
//
Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
ValueDecl *VD = DRE->getDecl();
if (VarDecl *Var = dyn_cast<VarDecl>(VD))
if (!ImportedLocalExternalDecls.count(Var))
return DRE;
Expr *Exp = new (Context) UnaryOperator(DRE, UnaryOperator::Deref,
DRE->getType(), DRE->getLocation());
// Need parens to enforce precedence.
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
Exp);
ReplaceStmt(DRE, PE);
return PE;
}
void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) {
SourceLocation LocStart = CE->getLParenLoc();
SourceLocation LocEnd = CE->getRParenLoc();
@ -5091,6 +5174,13 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
} else {
FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString());
Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
if (HasLocalVariableExternalStorage(*I)) {
QualType QT = (*I)->getType();
QT = Context->getPointerType(QT);
Exp = new (Context) UnaryOperator(Exp, UnaryOperator::AddrOf, QT,
SourceLocation());
}
}
InitExprs.push_back(Exp);
}
@ -5205,11 +5295,12 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
llvm::SmallVector<BlockDeclRefExpr *, 8> InnerBlockDeclRefs;
llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
InnerContexts.insert(BE->getBlockDecl());
ImportedLocalExternalDecls.clear();
GetInnerBlockDeclRefExprs(BE->getBody(),
InnerBlockDeclRefs, InnerContexts);
// Rewrite the block body in place.
RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
ImportedLocalExternalDecls.clear();
// Now we snarf the rewritten text and stash it away for later use.
std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
RewrittenBlockExprs[BE] = Str;
@ -5392,6 +5483,8 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
ValueDecl *VD = DRE->getDecl();
if (VD->hasAttr<BlocksAttr>())
return RewriteBlockDeclRefExpr(DRE);
if (HasLocalVariableExternalStorage(VD))
return RewriteLocalVariableExternalStorage(DRE);
}
if (CallExpr *CE = dyn_cast<CallExpr>(S)) {

View File

@ -119,19 +119,19 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,
}
assert(StartColNo <= EndColNo && "Invalid range!");
// Pick the first non-whitespace column.
while (StartColNo < SourceLine.size() &&
(SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t'))
++StartColNo;
// Pick the last non-whitespace column.
if (EndColNo > SourceLine.size())
EndColNo = SourceLine.size();
while (EndColNo-1 &&
(SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t'))
--EndColNo;
// If the start/end passed each other, then we are trying to highlight a range
// that just exists in whitespace, which must be some sort of other bug.
assert(StartColNo <= EndColNo && "Trying to highlight whitespace??");
@ -300,10 +300,10 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
if (E.isMacroID()) E = SM.getImmediateSpellingLoc(E);
Ranges[i] = SourceRange(S, E);
}
// Get the pretty name, according to #line directives etc.
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
// If this diagnostic is not in the main file, print out the "included from"
// lines.
if (LastWarningLoc != PLoc.getIncludeLoc()) {
@ -330,8 +330,10 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
unsigned FileOffset = LocInfo.second;
// Get information about the buffer it points into.
std::pair<const char*, const char*> BufferInfo = SM.getBufferData(FID);
const char *BufStart = BufferInfo.first;
bool Invalid = false;
const char *BufStart = SM.getBufferData(FID, &Invalid).data();
if (Invalid)
return;
unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
unsigned CaretEndColNo
@ -563,7 +565,7 @@ static unsigned findEndOfWord(unsigned Start,
// We have the start of a balanced punctuation sequence (quotes,
// parentheses, etc.). Determine the full sequence is.
llvm::SmallVector<char, 16> PunctuationEndStack;
llvm::SmallString<16> PunctuationEndStack;
PunctuationEndStack.push_back(EndPunct);
while (End < Length && !PunctuationEndStack.empty()) {
if (Str[End] == PunctuationEndStack.back())
@ -704,7 +706,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
if (DiagOpts->ShowLocation) {
if (DiagOpts->ShowColors)
OS.changeColor(savedColor, true);
// Emit a Visual Studio compatible line number syntax.
if (LangOpts && LangOpts->Microsoft) {
OS << PLoc.getFilename() << '(' << LineNo << ')';

View File

@ -199,6 +199,143 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/* Extract a float from X at index N into the first index of the return. */
#define _MM_PICK_OUT_PS(X, N) _mm_insert_ps (_mm_setzero_ps(), (X), \
_MM_MK_INSERTPS_NDX((N), 0, 0x0e))
/* Insert int into packed integer array at index. */
#define _mm_insert_epi8(X, I, N) (__extension__ ({ __v16qi __a = (__v16qi)X; \
__a[N] = I; \
__a;}))
#define _mm_insert_epi32(X, I, N) (__extension__ ({ __v4si __a = (__v4si)X; \
__a[N] = I; \
__a;}))
#ifdef __x86_64__
#define _mm_insert_epi64(X, I, N) (__extension__ ({ __v2di __a = (__v2di)X; \
__a[N] = I; \
__a;}))
#endif /* __x86_64__ */
/* Extract int from packed integer array at index. */
#define _mm_extract_epi8(X, N) (__extension__ ({ __v16qi __a = (__v16qi)X; \
__a[N];}))
#define _mm_extract_epi32(X, N) (__extension__ ({ __v4si __a = (__v4si)X; \
__a[N];}))
#ifdef __x86_64__
#define _mm_extract_epi64(X, N) (__extension__ ({ __v2di __a = (__v2di)X; \
__a[N];}))
#endif /* __x86_64 */
/* SSE4 128-bit Packed Integer Comparisons. */
static inline int __attribute__((__always_inline__, __nodebug__))
_mm_testz_si128(__m128i __M, __m128i __V)
{
return __builtin_ia32_ptestz128((__v2di)__M, (__v2di)__V);
}
static inline int __attribute__((__always_inline__, __nodebug__))
_mm_testc_si128(__m128i __M, __m128i __V)
{
return __builtin_ia32_ptestc128((__v2di)__M, (__v2di)__V);
}
static inline int __attribute__((__always_inline__, __nodebug__))
_mm_testnzc_si128(__m128i __M, __m128i __V)
{
return __builtin_ia32_ptestnzc128((__v2di)__M, (__v2di)__V);
}
#define _mm_test_all_ones(V) _mm_testc_si128((V), _mm_cmpeq_epi32((V), (V)))
#define _mm_test_mix_ones_zeros(M, V) _mm_testnzc_si128((M), (V))
#define _mm_test_all_zeros(M, V) _mm_testz_si128 ((V), (V))
/* SSE4 64-bit Packed Integer Comparisons. */
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_cmpeq_epi64(__m128i __V1, __m128i __V2)
{
return (__m128i) __builtin_ia32_pcmpeqq((__v2di)__V1, (__v2di)__V2);
}
/* SSE4 Packed Integer Sign-Extension. */
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_cvtepi8_epi16(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovsxbw128((__v16qi) __V);
}
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_cvtepi8_epi32(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovsxbd128((__v16qi) __V);
}
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_cvtepi8_epi64(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovsxbq128((__v16qi) __V);
}
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_cvtepi16_epi32(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovsxwd128((__v8hi) __V);
}
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_cvtepi16_epi64(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovsxwq128((__v8hi)__V);
}
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_cvtepi32_epi64(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovsxdq128((__v4si)__V);
}
/* SSE4 Packed Integer Zero-Extension. */
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_cvtepu8_epi16(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovzxbw128((__v16qi) __V);
}
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_cvtepu8_epi32(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovzxbd128((__v16qi)__V);
}
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_cvtepu8_epi64(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovzxbq128((__v16qi)__V);
}
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_cvtepu16_epi32(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovzxwd128((__v8hi)__V);
}
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_cvtepu16_epi64(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovzxwq128((__v8hi)__V);
}
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_cvtepu32_epi64(__m128i __V)
{
return (__m128i) __builtin_ia32_pmovzxdq128((__v4si)__V);
}
/* SSE4 Pack with Unsigned Saturation. */
static inline __m128i __attribute__((__always_inline__, __nodebug__))
_mm_packus_epi32(__m128i __V1, __m128i __V2)
{
return (__m128i) __builtin_ia32_packusdw128((__v4si)__V1, (__v4si)__V2);
}
/* SSE4 Multiple Packed Sums of Absolute Difference. */
#define _mm_mpsadbw_epu8(X, Y, M) __builtin_ia32_mpsadbw128((X), (Y), (M))
#endif /* __SSE4_1__ */

View File

@ -71,9 +71,7 @@ Entity EntityGetter::VisitNamedDecl(NamedDecl *D) {
DeclarationName GlobName;
if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) {
IdentifierInfo *GlobII =
&ProgImpl.getIdents().get(II->getNameStart(),
II->getNameStart() + II->getLength());
IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName());
GlobName = DeclarationName(GlobII);
} else {
Selector LocalSel = LocalName.getObjCSelector();
@ -140,9 +138,7 @@ Decl *EntityImpl::getDecl(ASTContext &AST) {
DeclarationName LocalName;
if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) {
IdentifierInfo &II =
AST.Idents.get(GlobII->getNameStart(),
GlobII->getNameStart() + GlobII->getLength());
IdentifierInfo &II = AST.Idents.get(GlobII->getName());
LocalName = DeclarationName(&II);
} else {
Selector GlobSel = Name.getObjCSelector();

View File

@ -29,9 +29,7 @@ Selector GlobalSelector::getSelector(ASTContext &AST) const {
for (unsigned i = 0, e = GlobSel.isUnarySelector() ? 1 : GlobSel.getNumArgs();
i != e; ++i) {
IdentifierInfo *GlobII = GlobSel.getIdentifierInfoForSlot(i);
IdentifierInfo *II =
&AST.Idents.get(GlobII->getNameStart(),
GlobII->getNameStart() + GlobII->getLength());
IdentifierInfo *II = &AST.Idents.get(GlobII->getName());
Ids.push_back(II);
}
@ -58,9 +56,7 @@ GlobalSelector GlobalSelector::get(Selector Sel, Program &Prog) {
for (unsigned i = 0, e = Sel.isUnarySelector() ? 1 : Sel.getNumArgs();
i != e; ++i) {
IdentifierInfo *II = Sel.getIdentifierInfoForSlot(i);
IdentifierInfo *GlobII =
&ProgImpl.getIdents().get(II->getNameStart(),
II->getNameStart() + II->getLength());
IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName());
Ids.push_back(GlobII);
}

View File

@ -18,10 +18,10 @@ LIBRARYNAME := clangIndex
BUILD_ARCHIVE = 1
ifeq ($(ARCH),PowerPC)
CXXFLAGS += -maltivec
CXX.Flags += -maltivec
endif
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
include $(LEVEL)/Makefile.common

View File

@ -229,14 +229,18 @@ unsigned Lexer::MeasureTokenLength(SourceLocation Loc,
// the token this macro expanded to.
Loc = SM.getInstantiationLoc(Loc);
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
std::pair<const char *,const char *> Buffer = SM.getBufferData(LocInfo.first);
const char *StrData = Buffer.first+LocInfo.second;
bool Invalid = false;
llvm::StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
if (Invalid)
return 0;
const char *StrData = Buffer.data()+LocInfo.second;
if (isWhitespace(StrData[0]))
return 0;
// Create a lexer starting at the beginning of this token.
Lexer TheLexer(Loc, LangOpts, Buffer.first, StrData, Buffer.second);
Lexer TheLexer(Loc, LangOpts, Buffer.begin(), StrData, Buffer.end());
TheLexer.SetCommentRetentionState(true);
Token TheTok;
TheLexer.LexFromRawLexer(TheTok);

View File

@ -806,7 +806,14 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
// Get the spelling of the token, which eliminates trigraphs, etc. We know
// that ThisTokBuf points to a buffer that is big enough for the whole token
// and 'spelled' tokens can only shrink.
unsigned ThisTokLen = PP.getSpelling(StringToks[i], ThisTokBuf);
bool StringInvalid = false;
unsigned ThisTokLen = PP.getSpelling(StringToks[i], ThisTokBuf,
&StringInvalid);
if (StringInvalid) {
hadError = 1;
continue;
}
const char *ThisTokEnd = ThisTokBuf+ThisTokLen-1; // Skip end quote.
// TODO: Input character set mapping support.
@ -904,8 +911,12 @@ unsigned StringLiteralParser::getOffsetOfStringByte(const Token &Tok,
llvm::SmallString<16> SpellingBuffer;
SpellingBuffer.resize(Tok.getLength());
bool StringInvalid = false;
const char *SpellingPtr = &SpellingBuffer[0];
unsigned TokLen = PP.getSpelling(Tok, SpellingPtr);
unsigned TokLen = PP.getSpelling(Tok, SpellingPtr, &StringInvalid);
if (StringInvalid) {
return 0;
}
assert(SpellingPtr[0] != 'L' && "Doesn't handle wide strings yet");

View File

@ -18,10 +18,10 @@ LIBRARYNAME := clangLex
BUILD_ARCHIVE = 1
ifeq ($(ARCH),PowerPC)
CXXFLAGS += -maltivec
CXX.Flags += -maltivec
endif
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
include $(LEVEL)/Makefile.common

View File

@ -471,7 +471,7 @@ void Preprocessor::HandleDirective(Token &Result) {
CurPPLexer->ParsingPreprocessorDirective = true;
++NumDirectives;
// We are about to read a token. For the multiple-include optimization FA to
// work, we have to remember if we had read any tokens *before* this
// pp-directive.
@ -964,7 +964,7 @@ bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc,
/// false if the > was found, otherwise it returns true if it finds and consumes
/// the EOM marker.
bool Preprocessor::ConcatenateIncludeName(
llvm::SmallVector<char, 128> &FilenameBuffer) {
llvm::SmallString<128> &FilenameBuffer) {
Token CurTok;
Lex(CurTok);
@ -1042,7 +1042,7 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok,
return;
}
bool isAngled =
bool isAngled =
GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
// If GetIncludeFilenameSpelling set the start ptr to null, there was an
// error.
@ -1070,7 +1070,7 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok,
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
return;
}
// Ask HeaderInfo if we should enter this #include file. If not, #including
// this file will have no effect.
if (!HeaderInfo.ShouldEnterIncludeFile(File, isImport))
@ -1512,7 +1512,7 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef,
IdentifierInfo *MII = MacroNameTok.getIdentifierInfo();
MacroInfo *MI = getMacroInfo(MII);
if (CurPPLexer->getConditionalStackDepth() == 0) {
// If the start of a top-level #ifdef and if the macro is not defined,
// inform MIOpt that this might be the start of a proper include guard.

View File

@ -170,7 +170,12 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
return true;
case tok::numeric_constant: {
llvm::SmallString<64> IntegerBuffer;
llvm::StringRef Spelling = PP.getSpelling(PeekTok, IntegerBuffer);
bool NumberInvalid = false;
llvm::StringRef Spelling = PP.getSpelling(PeekTok, IntegerBuffer,
&NumberInvalid);
if (NumberInvalid)
return true; // a diagnostic was already reported
NumericLiteralParser Literal(Spelling.begin(), Spelling.end(),
PeekTok.getLocation(), PP);
if (Literal.hadError)
@ -216,7 +221,10 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
}
case tok::char_constant: { // 'x'
llvm::SmallString<32> CharBuffer;
llvm::StringRef ThisTok = PP.getSpelling(PeekTok, CharBuffer);
bool CharInvalid = false;
llvm::StringRef ThisTok = PP.getSpelling(PeekTok, CharBuffer, &CharInvalid);
if (CharInvalid)
return true;
CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(),
PeekTok.getLocation(), PP);

View File

@ -80,9 +80,8 @@ bool Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
}
// Get the MemoryBuffer for this FID, if it fails, we fail.
const llvm::MemoryBuffer *InputFile =
getSourceManager().getBuffer(FID, &ErrorStr);
if (!ErrorStr.empty())
const llvm::MemoryBuffer *InputFile = getSourceManager().getBuffer(FID);
if (!InputFile)
return true;
EnterSourceFileWithLexer(new Lexer(FID, InputFile, *this), CurDir);

View File

@ -549,12 +549,12 @@ IdentifierInfo* PTHManager::LazilyCreateIdentifierInfo(unsigned PersistentID) {
return II;
}
IdentifierInfo* PTHManager::get(const char *NameStart, const char *NameEnd) {
IdentifierInfo* PTHManager::get(llvm::StringRef Name) {
PTHStringIdLookup& SL = *((PTHStringIdLookup*)StringIdLookup);
// Double check our assumption that the last character isn't '\0'.
assert(NameEnd==NameStart || NameStart[NameEnd-NameStart-1] != '\0');
PTHStringIdLookup::iterator I = SL.find(std::make_pair(NameStart,
NameEnd - NameStart));
assert(Name.empty() || Name.data()[Name.size()-1] != '\0');
PTHStringIdLookup::iterator I = SL.find(std::make_pair(Name.data(),
Name.size()));
if (I == SL.end()) // No identifier found?
return 0;
@ -662,7 +662,7 @@ class PTHStatCache : public StatSysCallCache {
CacheTy::iterator I = Cache.find(path);
// If we don't get a hit in the PTH file just forward to 'stat'.
if (I == Cache.end())
if (I == Cache.end())
return StatSysCallCache::stat(path, buf);
const PTHStatData& Data = *I;

View File

@ -52,7 +52,7 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
bool OwnsHeaders)
: Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()),
SourceMgr(SM), HeaderInfo(Headers), ExternalSource(0),
Identifiers(opts, IILookup), BuiltinInfo(Target), CodeCompletionFile(0),
Identifiers(opts, IILookup), BuiltinInfo(Target), CodeCompletionFile(0),
CurPPLexer(0), CurDirLookup(0), Callbacks(0), MacroArgCache(0) {
ScratchBuf = new ScratchBuffer(SourceMgr);
CounterValue = 0; // __COUNTER__ starts at 0.
@ -80,7 +80,7 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
// We haven't read anything from the external source.
ReadMacrosFromExternalSource = false;
// "Poison" __VA_ARGS__, which can only appear in the expansion of a macro.
// This gets unpoisoned where it is allowed.
(Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned();
@ -116,7 +116,7 @@ Preprocessor::~Preprocessor() {
// Free any cached macro expanders.
for (unsigned i = 0, e = NumCachedTokenLexers; i != e; ++i)
delete TokenLexerCache[i];
// Free any cached MacroArgs.
for (MacroArgs *ArgList = MacroArgCache; ArgList; )
ArgList = ArgList->deallocate();
@ -198,30 +198,30 @@ void Preprocessor::PrintStats() {
<< NumFastTokenPaste << " on the fast path.\n";
}
Preprocessor::macro_iterator
Preprocessor::macro_begin(bool IncludeExternalMacros) const {
if (IncludeExternalMacros && ExternalSource &&
Preprocessor::macro_iterator
Preprocessor::macro_begin(bool IncludeExternalMacros) const {
if (IncludeExternalMacros && ExternalSource &&
!ReadMacrosFromExternalSource) {
ReadMacrosFromExternalSource = true;
ExternalSource->ReadDefinedMacros();
}
return Macros.begin();
return Macros.begin();
}
Preprocessor::macro_iterator
Preprocessor::macro_end(bool IncludeExternalMacros) const {
if (IncludeExternalMacros && ExternalSource &&
Preprocessor::macro_iterator
Preprocessor::macro_end(bool IncludeExternalMacros) const {
if (IncludeExternalMacros && ExternalSource &&
!ReadMacrosFromExternalSource) {
ReadMacrosFromExternalSource = true;
ExternalSource->ReadDefinedMacros();
}
return Macros.end();
return Macros.end();
}
bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File,
unsigned TruncateAtLine,
bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File,
unsigned TruncateAtLine,
unsigned TruncateAtColumn) {
using llvm::MemoryBuffer;
@ -242,7 +242,7 @@ bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File,
for (; *Position; ++Position) {
if (*Position != '\r' && *Position != '\n')
continue;
// Eat \r\n or \n\r as a single line.
if ((Position[1] == '\r' || Position[1] == '\n') &&
Position[0] != Position[1])
@ -251,13 +251,13 @@ bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File,
break;
}
}
Position += TruncateAtColumn - 1;
// Truncate the buffer.
if (Position < Buffer->getBufferEnd()) {
MemoryBuffer *TruncatedBuffer
= MemoryBuffer::getMemBufferCopy(Buffer->getBufferStart(), Position,
MemoryBuffer *TruncatedBuffer
= MemoryBuffer::getMemBufferCopy(Buffer->getBufferStart(), Position,
Buffer->getBufferIdentifier());
SourceMgr.overrideFileContents(File, TruncatedBuffer);
}
@ -282,11 +282,19 @@ bool Preprocessor::isCodeCompletionFile(SourceLocation FileLoc) const {
/// UCNs, etc.
std::string Preprocessor::getSpelling(const Token &Tok,
const SourceManager &SourceMgr,
const LangOptions &Features) {
const LangOptions &Features,
bool *Invalid) {
assert((int)Tok.getLength() >= 0 && "Token character range is bogus!");
// If this token contains nothing interesting, return it directly.
const char* TokStart = SourceMgr.getCharacterData(Tok.getLocation());
bool CharDataInvalid = false;
const char* TokStart = SourceMgr.getCharacterData(Tok.getLocation(),
&CharDataInvalid);
if (Invalid)
*Invalid = CharDataInvalid;
if (CharDataInvalid)
return std::string();
if (!Tok.needsCleaning())
return std::string(TokStart, TokStart+Tok.getLength());
@ -310,8 +318,8 @@ std::string Preprocessor::getSpelling(const Token &Tok,
/// after trigraph expansion and escaped-newline folding. In particular, this
/// wants to get the true, uncanonicalized, spelling of things like digraphs
/// UCNs, etc.
std::string Preprocessor::getSpelling(const Token &Tok) const {
return getSpelling(Tok, SourceMgr, Features);
std::string Preprocessor::getSpelling(const Token &Tok, bool *Invalid) const {
return getSpelling(Tok, SourceMgr, Features, Invalid);
}
/// getSpelling - This method is used to get the spelling of a token into a
@ -325,7 +333,7 @@ std::string Preprocessor::getSpelling(const Token &Tok) const {
/// copy). The caller is not allowed to modify the returned buffer pointer
/// if an internal buffer is returned.
unsigned Preprocessor::getSpelling(const Token &Tok,
const char *&Buffer) const {
const char *&Buffer, bool *Invalid) const {
assert((int)Tok.getLength() >= 0 && "Token character range is bogus!");
// If this token is an identifier, just return the string from the identifier
@ -341,8 +349,16 @@ unsigned Preprocessor::getSpelling(const Token &Tok,
if (Tok.isLiteral())
TokStart = Tok.getLiteralData();
if (TokStart == 0)
TokStart = SourceMgr.getCharacterData(Tok.getLocation());
if (TokStart == 0) {
bool CharDataInvalid = false;
TokStart = SourceMgr.getCharacterData(Tok.getLocation(), &CharDataInvalid);
if (Invalid)
*Invalid = CharDataInvalid;
if (CharDataInvalid) {
Buffer = "";
return 0;
}
}
// If this token contains nothing interesting, return it directly.
if (!Tok.needsCleaning()) {
@ -368,7 +384,8 @@ unsigned Preprocessor::getSpelling(const Token &Tok,
/// SmallVector. Note that the returned StringRef may not point to the
/// supplied buffer if a copy can be avoided.
llvm::StringRef Preprocessor::getSpelling(const Token &Tok,
llvm::SmallVectorImpl<char> &Buffer) const {
llvm::SmallVectorImpl<char> &Buffer,
bool *Invalid) const {
// Try the fast path.
if (const IdentifierInfo *II = Tok.getIdentifierInfo())
return II->getName();
@ -378,7 +395,7 @@ llvm::StringRef Preprocessor::getSpelling(const Token &Tok,
Buffer.resize(Tok.getLength());
const char *Ptr = Buffer.data();
unsigned Len = getSpelling(Tok, Ptr);
unsigned Len = getSpelling(Tok, Ptr, Invalid);
return llvm::StringRef(Ptr, Len);
}
@ -446,7 +463,7 @@ SourceLocation Preprocessor::AdvanceToTokenCharacter(SourceLocation TokStart,
return TokStart.getFileLocWithOffset(PhysOffset);
}
SourceLocation Preprocessor::getLocForEndOfToken(SourceLocation Loc,
SourceLocation Preprocessor::getLocForEndOfToken(SourceLocation Loc,
unsigned Offset) {
if (Loc.isInvalid() || !Loc.isFileID())
return SourceLocation();
@ -456,7 +473,7 @@ SourceLocation Preprocessor::getLocForEndOfToken(SourceLocation Loc,
Len = Len - Offset;
else
return Loc;
return AdvanceToTokenCharacter(Loc, Len);
}
@ -519,7 +536,7 @@ IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier,
II = getIdentifierInfo(llvm::StringRef(BufPtr, Identifier.getLength()));
} else {
// Cleaning needed, alloca a buffer, clean into it, then use the buffer.
llvm::SmallVector<char, 64> IdentifierBuffer;
llvm::SmallString<64> IdentifierBuffer;
llvm::StringRef CleanedStr = getSpelling(Identifier, IdentifierBuffer);
II = getIdentifierInfo(CleanedStr);
}

View File

@ -325,7 +325,7 @@ void TokenLexer::Lex(Token &Tok) {
// returned by PasteTokens, not the pasted token.
if (PasteTokens(Tok))
return;
TokenIsFromPaste = true;
}
@ -379,7 +379,7 @@ void TokenLexer::Lex(Token &Tok) {
/// are more ## after it, chomp them iteratively. Return the result as Tok.
/// If this returns true, the caller should immediately return the token.
bool TokenLexer::PasteTokens(Token &Tok) {
llvm::SmallVector<char, 128> Buffer;
llvm::SmallString<128> Buffer;
const char *ResultTokStrPtr = 0;
do {
// Consume the ## operator.
@ -439,7 +439,11 @@ bool TokenLexer::PasteTokens(Token &Tok) {
SourceManager &SourceMgr = PP.getSourceManager();
FileID LocFileID = SourceMgr.getFileID(ResultTokLoc);
const char *ScratchBufStart = SourceMgr.getBufferData(LocFileID).first;
bool Invalid = false;
const char *ScratchBufStart
= SourceMgr.getBufferData(LocFileID, &Invalid).data();
if (Invalid)
return false;
// Make a lexer to lex this string from. Lex just this one token.
// Make a lexer object so that we lex and expand the paste result.
@ -506,8 +510,7 @@ bool TokenLexer::PasteTokens(Token &Tok) {
if (Tok.is(tok::identifier)) {
// Look up the identifier info for the token. We disabled identifier lookup
// by saying we're skipping contents, so we need to do this manually.
IdentifierInfo *II = PP.LookUpIdentifierInfo(Tok, ResultTokStrPtr);
Tok.setIdentifierInfo(II);
PP.LookUpIdentifierInfo(Tok, ResultTokStrPtr);
}
return false;
}

View File

@ -15,7 +15,7 @@ LEVEL = ../../../..
LIBRARYNAME := clangParse
BUILD_ARCHIVE = 1
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
include $(LEVEL)/Makefile.common

View File

@ -52,7 +52,7 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
Actions.CodeCompleteNamespaceDecl(CurScope);
ConsumeToken();
}
SourceLocation IdentLoc;
IdentifierInfo *Ident = 0;
@ -130,7 +130,7 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
Actions.CodeCompleteNamespaceAliasDecl(CurScope);
ConsumeToken();
}
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
@ -165,7 +165,7 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
Parser::DeclPtrTy Parser::ParseLinkage(ParsingDeclSpec &DS,
unsigned Context) {
assert(Tok.is(tok::string_literal) && "Not a string literal!");
llvm::SmallVector<char, 8> LangBuffer;
llvm::SmallString<8> LangBuffer;
// LangBuffer is guaranteed to be big enough.
llvm::StringRef Lang = PP.getSpelling(Tok, LangBuffer);
@ -183,7 +183,7 @@ Parser::DeclPtrTy Parser::ParseLinkage(ParsingDeclSpec &DS,
if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
Attr = ParseCXX0XAttributes();
}
if (Tok.isNot(tok::l_brace)) {
ParseDeclarationOrFunctionDefinition(DS, Attr.AttrList);
return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec,
@ -222,7 +222,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
Actions.CodeCompleteUsing(CurScope);
ConsumeToken();
}
if (Tok.is(tok::kw_namespace))
// Next token after 'using' is 'namespace' so it must be using-directive
return ParseUsingDirective(Context, UsingLoc, DeclEnd, Attr.AttrList);
@ -259,7 +259,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
Actions.CodeCompleteUsingDirective(CurScope);
ConsumeToken();
}
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
@ -332,20 +332,20 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
return DeclPtrTy();
}
// Parse the unqualified-id. We allow parsing of both constructor and
// Parse the unqualified-id. We allow parsing of both constructor and
// destructor names and allow the action module to diagnose any semantic
// errors.
UnqualifiedId Name;
if (ParseUnqualifiedId(SS,
if (ParseUnqualifiedId(SS,
/*EnteringContext=*/false,
/*AllowDestructorName=*/true,
/*AllowConstructorName=*/true,
/*ObjectType=*/0,
/*AllowConstructorName=*/true,
/*ObjectType=*/0,
Name)) {
SkipUntil(tok::semi);
return DeclPtrTy();
}
// Parse (optional) attributes (most likely GNU strong-using extension).
llvm::OwningPtr<AttributeList> AttrList;
if (Tok.is(tok::kw___attribute))
@ -354,7 +354,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
// Eat ';'.
DeclEnd = Tok.getLocation();
ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
AttrList ? "attributes list" : "using declaration",
AttrList ? "attributes list" : "using declaration",
tok::semi);
return Actions.ActOnUsingDeclaration(CurScope, AS, true, UsingLoc, SS, Name,
@ -502,26 +502,26 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
Diag(IdLoc, diag::err_unknown_template_name)
<< Id;
}
if (!Template)
return true;
// Form the template name
// Form the template name
UnqualifiedId TemplateName;
TemplateName.setIdentifier(Id, IdLoc);
// Parse the full template-id, then turn it into a type.
if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName,
SourceLocation(), true))
return true;
if (TNK == TNK_Dependent_template_name)
AnnotateTemplateIdTokenAsType(SS);
// If we didn't end up with a typename token, there's nothing more we
// can do.
if (Tok.isNot(tok::annot_typename))
return true;
// Retrieve the type from the annotation token, consume that token, and
// return.
EndLocation = Tok.getAnnotationEndLoc();
@ -532,7 +532,7 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
// We have an identifier; check whether it is actually a type.
TypeTy *Type = Actions.getTypeName(*Id, IdLoc, CurScope, SS, true);
if (!Type) {
if (!Type) {
Diag(IdLoc, diag::err_expected_class_name);
return true;
}
@ -601,7 +601,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
Actions.CodeCompleteTag(CurScope, TagType);
ConsumeToken();
}
AttributeList *AttrList = 0;
// If attributes exist after tag, parse them.
if (Tok.is(tok::kw___attribute))
@ -610,7 +610,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// If declspecs exist after tag, parse them.
if (Tok.is(tok::kw___declspec))
AttrList = ParseMicrosoftDeclSpec(AttrList);
// If C++0x attributes exist here, parse them.
// FIXME: Are we consistent with the ordering of parsing of different
// styles of attributes?
@ -642,7 +642,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (getLang().CPlusPlus) {
// "FOO : BAR" is not a potential typo for "FOO::BAR".
ColonProtectionRAIIObject X(*this);
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true);
if (SS.isSet())
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
@ -658,21 +658,21 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (Tok.is(tok::identifier)) {
Name = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
if (Tok.is(tok::less)) {
// The name was supposed to refer to a template, but didn't.
// The name was supposed to refer to a template, but didn't.
// Eat the template argument list and try to continue parsing this as
// a class (or template thereof).
TemplateArgList TemplateArgs;
SourceLocation LAngleLoc, RAngleLoc;
if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS,
if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS,
true, LAngleLoc,
TemplateArgs, RAngleLoc)) {
// We couldn't parse the template argument list at all, so don't
// try to give any location information for the list.
LAngleLoc = RAngleLoc = SourceLocation();
}
Diag(NameLoc, diag::err_explicit_spec_non_template)
<< (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
<< (TagType == DeclSpec::TST_class? 0
@ -680,30 +680,30 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
: 2)
<< Name
<< SourceRange(LAngleLoc, RAngleLoc);
// Strip off the last template parameter list if it was empty, since
// Strip off the last template parameter list if it was empty, since
// we've removed its template argument list.
if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
if (TemplateParams && TemplateParams->size() > 1) {
TemplateParams->pop_back();
} else {
TemplateParams = 0;
const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
= ParsedTemplateInfo::NonTemplate;
}
} else if (TemplateInfo.Kind
== ParsedTemplateInfo::ExplicitInstantiation) {
// Pretend this is just a forward declaration.
TemplateParams = 0;
const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
= ParsedTemplateInfo::NonTemplate;
const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc
const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc
= SourceLocation();
const_cast<ParsedTemplateInfo&>(TemplateInfo).ExternLoc
= SourceLocation();
}
}
} else if (Tok.is(tok::annot_template_id)) {
TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
@ -896,7 +896,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// less common call.
if (IsDependent)
TypeResult = Actions.ActOnDependentTag(CurScope, TagType, TUK,
SS, Name, StartLoc, NameLoc);
SS, Name, StartLoc, NameLoc);
}
// If there is a body, parse it and inform the actions module.
@ -927,11 +927,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// FIXME: The DeclSpec should keep the locations of both the keyword and the
// name (if there is one).
SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
if (DS.SetTypeSpecType(TagType, TSTLoc, PrevSpec, DiagID,
Result, Owned))
Diag(StartLoc, DiagID) << PrevSpec;
// At this point, we've successfully parsed a class-specifier in 'definition'
// form (e.g. "struct foo { int x; }". While we could just return here, we're
// going to look at what comes after it to improve error recovery. If an
@ -984,14 +984,14 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (!isKnownToBeTypeSpecifier(NextToken()))
ExpectedSemi = false;
break;
case tok::r_brace: // struct bar { struct foo {...} }
case tok::r_brace: // struct bar { struct foo {...} }
// Missing ';' at end of struct is accepted as an extension in C mode.
if (!getLang().CPlusPlus)
ExpectedSemi = false;
break;
}
if (ExpectedSemi) {
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
TagType == DeclSpec::TST_class ? "class"
@ -1000,7 +1000,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// to ';' so that the rest of the code recovers as though there were an
// ';' after the definition.
PP.EnterToken(Tok);
Tok.setKind(tok::semi);
Tok.setKind(tok::semi);
}
}
}
@ -1084,7 +1084,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
// Parse optional '::' and optional nested-name-specifier.
CXXScopeSpec SS;
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0,
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0,
/*EnteringContext=*/false);
// The location of the base class itself.
@ -1251,7 +1251,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
// is a bitfield.
ColonProtectionRAIIObject X(*this);
CXX0XAttributeList AttrList;
// Optional C++0x attribute-specifier
if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
@ -1259,7 +1259,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (Tok.is(tok::kw_using)) {
// FIXME: Check for template aliases
if (AttrList.HasAttr)
Diag(AttrList.Range.getBegin(), diag::err_attributes_not_allowed)
<< AttrList.Range;
@ -1628,14 +1628,14 @@ void Parser::ParseConstructorInitializer(DeclPtrTy ConstructorDecl) {
llvm::SmallVector<MemInitTy*, 4> MemInitializers;
bool AnyErrors = false;
do {
MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
if (!MemInit.isInvalid())
MemInitializers.push_back(MemInit.get());
else
AnyErrors = true;
if (Tok.is(tok::comma))
ConsumeToken();
else if (Tok.is(tok::l_brace))
@ -1869,7 +1869,7 @@ CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) {
ConsumeBracket();
ConsumeBracket();
if (Tok.is(tok::comma)) {
Diag(Tok.getLocation(), diag::err_expected_ident);
ConsumeToken();
@ -1884,7 +1884,7 @@ CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) {
IdentifierInfo *ScopeName = 0, *AttrName = Tok.getIdentifierInfo();
SourceLocation ScopeLoc, AttrLoc = ConsumeToken();
// scoped attribute
if (Tok.is(tok::coloncolon)) {
ConsumeToken();
@ -1894,7 +1894,7 @@ CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) {
SkipUntil(tok::r_square, tok::comma, true, true);
continue;
}
ScopeName = AttrName;
ScopeLoc = AttrLoc;

View File

@ -375,6 +375,10 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
AtEnd.setBegin(AtLoc);
AtEnd.setEnd(Tok.getLocation());
break;
} else if (DirectiveKind == tok::objc_not_keyword) {
Diag(Tok, diag::err_objc_unknown_at);
SkipUntil(tok::semi);
continue;
}
// Eat the identifier.

View File

@ -43,8 +43,13 @@ void html::HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E,
// Include the whole end token in the range.
EOffset += Lexer::MeasureTokenLength(E, R.getSourceMgr(), R.getLangOpts());
bool Invalid = false;
const char *BufferStart = SM.getBufferData(FID, &Invalid).data();
if (Invalid)
return;
HighlightRange(R.getEditBuffer(FID), BOffset, EOffset,
SM.getBufferData(FID).first, StartTag, EndTag);
BufferStart, StartTag, EndTag);
}
/// HighlightRange - This is the same as the above method, but takes

Some files were not shown because too many files have changed in this diff Show More