diff options
author | Ted Kremenek <kremenek@apple.com> | 2008-02-24 03:55:14 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2008-02-24 03:55:14 +0000 |
commit | ca63fa00786e51c207c829f4182f11a6c6b552be (patch) | |
tree | 34e3a6ebeaa746676b09a865d373be8fda627f37 | |
parent | 6bb816a3b895e9c983d89b22d510dca58a0eb75e (diff) |
Two more Windows-related fixes:
- More enum signeness bitfield fixes (MSVC treats enums as signed).
- Fixed in Lex/HeaderSearch.cpp an unsafe copy between two
HeaderSearch::PerFileInfo entries in a common vector. The copy involved two
calls to getFileInfo() within the assignment; these calls could have
side-effects that enlarged the internal vector, and with MSVC this would
invalidate one of the values in the assignment.
Patch by Argiris Kirtzidis!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47536 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | Lex/HeaderSearch.cpp | 34 | ||||
-rw-r--r-- | include/clang/AST/Decl.h | 12 | ||||
-rw-r--r-- | include/clang/AST/DeclObjC.h | 24 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 7 | ||||
-rw-r--r-- | include/clang/Basic/IdentifierTable.h | 7 | ||||
-rw-r--r-- | include/clang/Lex/DirectoryLookup.h | 5 | ||||
-rw-r--r-- | include/clang/Lex/HeaderSearch.h | 5 | ||||
-rw-r--r-- | include/clang/Parse/DeclSpec.h | 5 |
8 files changed, 74 insertions, 25 deletions
diff --git a/Lex/HeaderSearch.cpp b/Lex/HeaderSearch.cpp index bd36f35d49..899c9d87a9 100644 --- a/Lex/HeaderSearch.cpp +++ b/Lex/HeaderSearch.cpp @@ -228,7 +228,22 @@ const FileEntry *HeaderSearch::LookupFile(const char *FilenameStart, if (const FileEntry *FE = FileMgr.getFile(TmpDir.begin(), TmpDir.end())) { // Leave CurDir unset. // This file is a system header or C++ unfriendly if the old file is. - getFileInfo(FE).DirInfo = getFileInfo(CurFileEnt).DirInfo; + + // Note: Don't use: + // + // getFileInfo(FE).DirInfo = getFileInfo(CurFileEnt).DirInfo; + // + // MSVC, behind the scenes, does this: + // + // PerFileInfo &pf1 = getFileInfo(CurFileEnt); + // PerFileInfo &pf2 = getFileInfo(FE); + // pf2.DirInfo = pf1.DirInfo + // + // The problem is that if there's a resize() of the FileInfo vector during + // the getFileInfo(FE) call, pf1 will point to invalid data. To fix + // this problem, make the assignment through a temporary. + unsigned int tmp = getFileInfo(CurFileEnt).DirInfo; + getFileInfo(FE).DirInfo = tmp; return FE; } } @@ -357,7 +372,22 @@ LookupSubframeworkHeader(const char *FilenameStart, } // This file is a system header or C++ unfriendly if the old file is. - getFileInfo(FE).DirInfo = getFileInfo(ContextFileEnt).DirInfo; + + // Note: Don't use: + // + // getFileInfo(FE).DirInfo = getFileInfo(ContextFileEnt).DirInfo; + // + // MSVC, behind the scenes, does this: + // + // PerFileInfo &pf1 = getFileInfo(ContextFileEnt); + // PerFileInfo &pf2 = getFileInfo(FE); + // pf2.DirInfo = pf1.DirInfo + // + // The problem is that if there's a resize() of the FileInfo vector during + // the getFileInfo(FE) call, pf1 will point to invalid data. The solution + // is to make the assignment through a temporary. + unsigned int tmp = getFileInfo(ContextFileEnt).DirInfo; + getFileInfo(FE).DirInfo = tmp; return FE; } diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 0bf737c1ea..b2f6be0567 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -408,7 +408,9 @@ public: : VarDecl(ParmVar, L, Id, T, S, PrevDecl), objcDeclQualifier(OBJC_TQ_None) {} - ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; } + ObjCDeclQualifier getObjCDeclQualifier() const { + return ObjCDeclQualifier(objcDeclQualifier); + } void setObjCDeclQualifier(ObjCDeclQualifier QTVal) { objcDeclQualifier = QTVal; } @@ -417,9 +419,10 @@ public: static bool classof(const ParmVarDecl *D) { return true; } private: + // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum /// FIXME: Also can be paced into the bitfields in Decl. /// in, inout, etc. - ObjCDeclQualifier objcDeclQualifier : 6; + unsigned objcDeclQualifier : 6; protected: /// EmitImpl - Serialize this ParmVarDecl. Called by Decl::Emit. @@ -474,7 +477,7 @@ public: QualType getResultType() const { return cast<FunctionType>(getType())->getResultType(); } - StorageClass getStorageClass() const { return SClass; } + StorageClass getStorageClass() const { return StorageClass(SClass); } bool isInline() const { return IsInline; } // Implement isa/cast/dyncast/etc. @@ -494,7 +497,8 @@ private: /// function. ScopedDecl *DeclChain; - StorageClass SClass : 2; + // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum + unsigned SClass : 2; bool IsInline : 1; protected: diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index c2048115c3..0b5338e731 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -58,11 +58,13 @@ private: bool IsInstance : 1; bool IsVariadic : 1; + // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum /// @required/@optional - ImplementationControl DeclImplementation : 2; + unsigned DeclImplementation : 2; + // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum /// in, inout, etc. - ObjCDeclQualifier objcDeclQualifier : 6; + unsigned objcDeclQualifier : 6; // Context this method is declared in. NamedDecl *MethodContext; @@ -104,7 +106,9 @@ public: MethodAttrs(M), EndLoc(endLoc), Body(0), SelfDecl(0) {} virtual ~ObjCMethodDecl(); - ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; } + ObjCDeclQualifier getObjCDeclQualifier() const { + return ObjCDeclQualifier(objcDeclQualifier); + } void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; } // Location information, modeled after the Stmt API. @@ -149,7 +153,7 @@ public: DeclImplementation = ic; } ImplementationControl getImplementationControl() const { - return DeclImplementation; + return ImplementationControl(DeclImplementation); } Stmt *const getBody() const { return Body; } void setBody(Stmt *B) { Body = B; } @@ -365,13 +369,14 @@ public: None, Private, Protected, Public, Package }; void setAccessControl(AccessControl ac) { DeclAccess = ac; } - AccessControl getAccessControl() const { return DeclAccess; } + AccessControl getAccessControl() const { return AccessControl(DeclAccess); } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == ObjCIvar; } static bool classof(const ObjCIvarDecl *D) { return true; } private: - AccessControl DeclAccess : 3; + // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum + unsigned DeclAccess : 3; }; @@ -873,8 +878,9 @@ private: // FIXME: Property is not an ivar. ObjCIvarDecl **PropertyDecls; int NumPropertyDecls; - - PropertyAttributeKind PropertyAttributes : 8; + + // NOTE: VC++ treats enums as signed, avoid using PropertyAttributeKind enum + unsigned PropertyAttributes : 8; IdentifierInfo *GetterName; // getter name of NULL if no getter IdentifierInfo *SetterName; // setter name of NULL if no setter @@ -892,7 +898,7 @@ public: void setNumPropertyDecls(int num) { NumPropertyDecls = num; } const PropertyAttributeKind getPropertyAttributes() const - { return PropertyAttributes; } + { return PropertyAttributeKind(PropertyAttributes); } void setPropertyAttributes(PropertyAttributeKind PRVal) { PropertyAttributes = (PropertyAttributeKind) (PropertyAttributes | PRVal); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index fc115c8a39..e434ea2c0b 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -552,8 +552,9 @@ private: /// ElementType - The element type of the array. QualType ElementType; + // NOTE: VC++ treats enums as signed, avoid using the ArraySizeModifier enum /// NOTE: These fields are packed into the bitfields space in the Type class. - ArraySizeModifier SizeModifier : 2; + unsigned SizeModifier : 2; /// IndexTypeQuals - Capture qualifiers in declarations like: /// 'int X[static restrict 4]'. For function parameters only. @@ -566,7 +567,9 @@ protected: friend class ASTContext; // ASTContext creates these. public: QualType getElementType() const { return ElementType; } - ArraySizeModifier getSizeModifier() const { return SizeModifier; } + ArraySizeModifier getSizeModifier() const { + return ArraySizeModifier(SizeModifier); + } unsigned getIndexTypeQualifier() const { return IndexTypeQuals; } QualType getBaseType() const { diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 97119261d9..fa3143f656 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -40,7 +40,8 @@ class IdentifierInfo { // signed char and TokenKinds > 127 won't be handled correctly. unsigned TokenID : 8; // Front-end token ID or tok::identifier. unsigned BuiltinID : 9; // ID if this is a builtin (__builtin_inf). - tok::ObjCKeywordKind ObjCID : 5; // ID for objc @ keyword like @'protocol'. + // NOTE: VC++ treats enums as signed, avoid using tok::ObjCKeywordKind enum + unsigned ObjCID : 5; // ID for objc @ keyword like @'protocol'. bool HasMacro : 1; // True if there is a #define for this. bool IsExtension : 1; // True if identifier is a lang extension. bool IsPoisoned : 1; // True if identifier is poisoned. @@ -91,7 +92,9 @@ public: /// getObjCKeywordID - Return the Objective-C keyword ID for the this /// identifier. For example, 'class' will return tok::objc_class if ObjC is /// enabled. - tok::ObjCKeywordKind getObjCKeywordID() const { return ObjCID; } + tok::ObjCKeywordKind getObjCKeywordID() const { + return tok::ObjCKeywordKind(ObjCID); + } void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCID = ID; } /// getBuiltinID - Return a value indicating whether this is a builtin diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h index eb897618ef..eb9bf5dbbb 100644 --- a/include/clang/Lex/DirectoryLookup.h +++ b/include/clang/Lex/DirectoryLookup.h @@ -48,9 +48,10 @@ private: const HeaderMap *Map; } u; + // NOTE: VC++ treats enums as signed, avoid using the DirType enum /// DirCharacteristic - The type of directory this is, one of the DirType enum /// values. - DirType DirCharacteristic : 2; + unsigned DirCharacteristic : 2; /// UserSupplied - True if this is a user-supplied directory. /// @@ -110,7 +111,7 @@ public: /// DirCharacteristic - The type of directory this is, one of the DirType enum /// values. - DirType getDirCharacteristic() const { return DirCharacteristic; } + DirType getDirCharacteristic() const { return DirType(DirCharacteristic); } /// isUserSupplied - True if this is a user-supplied directory. /// diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index a7f8a116fb..3c43213be6 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -45,10 +45,11 @@ class HeaderSearch { /// isImport - True if this is a #import'd or #pragma once file. bool isImport : 1; + // NOTE: VC++ treats enums as signed, avoid using DirectoryLookup::DirType /// DirInfo - Keep track of whether this is a system header, and if so, /// whether it is C++ clean or not. This can be set by the include paths or /// by #pragma gcc system_header. - DirectoryLookup::DirType DirInfo : 2; + unsigned DirInfo : 2; /// NumIncludes - This is the number of times the file has been included /// already. @@ -155,7 +156,7 @@ public: /// getFileDirFlavor - Return whether the specified file is a normal header, /// a system header, or a C++ friendly system header. DirectoryLookup::DirType getFileDirFlavor(const FileEntry *File) { - return getFileInfo(File).DirInfo; + return DirectoryLookup::DirType(getFileInfo(File).DirInfo); } /// MarkFileIncludeOnce - Mark the specified file as a "once only" file, e.g. diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index b15279379e..68a019a4a3 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -330,7 +330,7 @@ public: { objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); } const ObjCPropertyAttributeKind getPropertyAttributes() const - { return PropertyAttributes; } + { return ObjCPropertyAttributeKind(PropertyAttributes); } void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) { PropertyAttributes = (ObjCPropertyAttributeKind) (PropertyAttributes | PRVal); @@ -349,7 +349,8 @@ private: // (space saving is negligible). ObjCDeclQualifier objcDeclQualifier : 6; - ObjCPropertyAttributeKind PropertyAttributes : 8; + // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind + unsigned PropertyAttributes : 8; IdentifierInfo *GetterName; // getter name of NULL if no getter IdentifierInfo *SetterName; // setter name of NULL if no setter }; |