]> granicus.if.org Git - clang/commitdiff
Two more Windows-related fixes:
authorTed Kremenek <kremenek@apple.com>
Sun, 24 Feb 2008 03:55:14 +0000 (03:55 +0000)
committerTed Kremenek <kremenek@apple.com>
Sun, 24 Feb 2008 03:55:14 +0000 (03:55 +0000)
- 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

Lex/HeaderSearch.cpp
include/clang/AST/Decl.h
include/clang/AST/DeclObjC.h
include/clang/AST/Type.h
include/clang/Basic/IdentifierTable.h
include/clang/Lex/DirectoryLookup.h
include/clang/Lex/HeaderSearch.h
include/clang/Parse/DeclSpec.h

index bd36f35d49bc4cd68e106d95b492111cfa5f43fb..899c9d87a93d49fd53c777a7c9a049a720fad8e5 100644 (file)
@@ -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;
 }
 
index 0bf737c1ea4ef7c46aa52c13d896b8d9273c89ce..b2f6be05671e60bf002305c0441dcbac9ce49e23 100644 (file)
@@ -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:
index c2048115c3bd6a52394e50378044eb3330b4ded8..0b5338e7313226fa3c55fb46fbc6d29a6decf39f 100644 (file)
@@ -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);
index fc115c8a3903577451a76a79dfdd6159ba0b4dd0..e434ea2c0bfbfeea812ac113100d2161ac8bdaed 100644 (file)
@@ -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 {
index 97119261d95f0a25268b3fdaa2eb1c1b70428c8b..fa3143f6560f4ffa9e96be39f6cd73d9786df47b 100644 (file)
@@ -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
index eb897618ef3daf3f04d63f5454246eb487ae412d..eb9bf5dbbb20c27103624549f242b95ca110265a 100644 (file)
@@ -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.
   ///
index a7f8a116fb7085d691f76fa77e24a51b8484b0f6..3c43213be6f921740dd408c2721984ecbb0c376c 100644 (file)
@@ -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.
index b15279379e8daf0c5f9d7658d165a843e7bd4774..68a019a4a30b37bc415da9385d26369499b523c2 100644 (file)
@@ -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
 };