Update clang to r98631.
This commit is contained in:
parent
a16e9ac1f1
commit
4a37f65f1c
8
Makefile
8
Makefile
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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()); }
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
///
|
||||
|
167
include/clang/AST/DeclFriend.h
Normal file
167
include/clang/AST/DeclFriend.h
Normal 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
|
@ -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; }
|
||||
|
@ -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 {
|
||||
|
@ -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() {}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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">;
|
||||
|
@ -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">;
|
||||
|
@ -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; };
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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">;
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -121,7 +121,7 @@ class ASTUnit {
|
||||
};
|
||||
friend class ConcurrencyCheck;
|
||||
|
||||
ASTUnit(bool MainFileIsAST);
|
||||
ASTUnit(Diagnostic &Diag, bool MainFileIsAST);
|
||||
~ASTUnit();
|
||||
|
||||
bool isMainFileAST() const { return MainFileIsAST; }
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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':
|
||||
|
@ -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(),
|
||||
|
@ -11,6 +11,7 @@ add_clang_library(clangAST
|
||||
Decl.cpp
|
||||
DeclBase.cpp
|
||||
DeclCXX.cpp
|
||||
DeclFriend.cpp
|
||||
DeclGroup.cpp
|
||||
DeclObjC.cpp
|
||||
DeclPrinter.cpp
|
||||
|
@ -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,
|
||||
|
@ -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"
|
||||
|
@ -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
41
lib/AST/DeclFriend.cpp
Normal 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;
|
||||
}
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 *
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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() &&
|
||||
|
@ -437,7 +437,8 @@ class CodeGenModule : public BlockModule {
|
||||
GVA_C99Inline,
|
||||
GVA_CXXInline,
|
||||
GVA_StrongExternal,
|
||||
GVA_TemplateInstantiation
|
||||
GVA_TemplateInstantiation,
|
||||
GVA_ExplicitTemplateInstantiation
|
||||
};
|
||||
|
||||
llvm::GlobalVariable::LinkageTypes
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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()) {
|
||||
|
@ -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))
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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) {
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -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));
|
||||
|
@ -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)) {
|
||||
|
@ -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 << ')';
|
||||
|
@ -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__ */
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user