r220493 - Add a "signature" to AST files to verify that they haven't changed

Richard Smith richard at metafoo.co.uk
Thu Oct 23 16:52:08 PDT 2014


On Thu, Oct 23, 2014 at 3:54 PM, Ben Langmuir <blangmuir at apple.com> wrote:

>
> On Oct 23, 2014, at 3:34 PM, Richard Smith <richard at metafoo.co.uk> wrote:
>
> On Thu, Oct 23, 2014 at 11:41 AM, Ben Langmuir <blangmuir at apple.com>
> wrote:
>
>>
>> On Oct 23, 2014, at 11:24 AM, David Blaikie <dblaikie at gmail.com> wrote:
>>
>>
>>
>> On Thu, Oct 23, 2014 at 11:05 AM, Ben Langmuir <blangmuir at apple.com>
>> wrote:
>>
>>> Author: benlangmuir
>>> Date: Thu Oct 23 13:05:36 2014
>>> New Revision: 220493
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=220493&view=rev
>>> Log:
>>> Add a "signature" to AST files to verify that they haven't changed
>>>
>>> Since the order of the IDs in the AST file (e.g. DeclIDs, SelectorIDs)
>>> is not stable,
>>
>>
>> Um... when you say "not stable" what do you mean? (& when you say
>> "nothing changed" what do you mean)
>>
>>
>> Identifiers, decls, macros, etc. are referred to by ID numbers, which
>> depend on the order the entity is looked at during serialization.  This in
>> turn often depends on hash-table iteration order and is not stable across
>> runs.  When a module refers to a name in one of its imports, it will find
>> the wrong name if the order has changed since it was first built.
>>
>> By “not changed” I mean that the sources have not changed.
>>
>>
>> It's pretty important that the compiler produces identical bytes given
>> identical input. We're pretty clear about fixing any cases where it doesn't
>> (but maybe we haven't been as rigorous about that with AST serialization? I
>> don't know - I'b be a bit scared if we haven’t)
>>
>>
>> Maybe someone more familiar with the history of the ASTWriter can
>> comment? +rsmith, +dgregor, +akyrtzidis
>>
>
> Non-deterministic output is a bug, but it's been lower priority than other
> stuff I've been looking at up until now. It's likely to get near the top of
> my priority stack fairly soon. So... this patch is /technically/ making
> that existing problem worse by adding more nondeterminism to the output,
> but since it's also fixing an immediate problem, I suggest we keep this
> change in place until we've fixed the other nondeterminism, then revert it.
>
> Does that seem reasonable?
>
>
> How do you intend to maintain the deterministic output?  My first concern
> is that if it later regresses, the kind of bug report we will get is ‘I
> used modules and this name lookup failed’.
>

I was intending on adding a test that builds some module twice and checks
that it gives the same output.

Also, we can rebuild a module and it legitimately changes (you rename ‘A’
> to ‘B’ inside one of the headers), but still the resulting pcm doesn’t have
> a different size or mod-time from the previous version.
>

Hmm, aren't we already checking that the mtimes of the input files are the
same as when we built the module before we use a module from the cache? We
need to get the "files changed after I read them but before I built the pcm
file" case right, whether it be by checking mtimes or by computing a hash
or whatever else.

This has the same problem as the non-deterministic output, although it is
> much less likely to happen in practice.  I suggest we continue to have a
> ‘signature’ but change it to be a hash of the file contents so that it
> doesn’t introduce any additional non-determinism.  We only need to hash the
> file when it is written, so module loading won’t regress.
>

We can't completely discount the time cost of building a module; that will
still be on the critical path for slower builds. If this hashing is
low-overhead, it seems fine to me.

In general, I think having a stable output would be great and I’m happy to
> pitch in with testing and to help with the Objective-C bits :-)
>

Great, thanks!

Ben
>
>
> I briefly looked at making the IDs deterministic, but I saw several hash
>> tables being iterated over with no apparently guarantee of order, and
>> figured we were not trying to produce identical bytes.  We certainly
>> *aren’t* producing identical bytes, and when this happens it causes utter
>> insanity.
>>
>> Ben
>>
>>
>>
>>> it is not safe to load an AST file that depends on
>>> another AST file that has been rebuilt since the importer was built,
>>> even if "nothing changed". We previously used size and modtime to check
>>> this, but I've seen cases where a module rebuilt quickly enough to foil
>>> this check and caused very hard to debug build errors.
>>>
>>> To save cycles when we're loading the AST, we just generate a random
>>> nonce value and check that it hasn't changed when we load an imported
>>> module, rather than actually hash the whole file.
>>>
>>> This is slightly complicated by the fact that we need to verify the
>>> signature inside addModule, since we might otherwise consider that a
>>> mdoule is "OutOfDate" when really it is the importer that is out of
>>> date. I didn't see any regressions in module load time after this
>>> change.
>>>
>>> Added:
>>>     cfe/trunk/test/Modules/rebuild.m
>>> Modified:
>>>     cfe/trunk/include/clang/Serialization/ASTBitCodes.h
>>>     cfe/trunk/include/clang/Serialization/ASTReader.h
>>>     cfe/trunk/include/clang/Serialization/Module.h
>>>     cfe/trunk/include/clang/Serialization/ModuleManager.h
>>>     cfe/trunk/lib/Serialization/ASTReader.cpp
>>>     cfe/trunk/lib/Serialization/ASTWriter.cpp
>>>     cfe/trunk/lib/Serialization/GlobalModuleIndex.cpp
>>>     cfe/trunk/lib/Serialization/Module.cpp
>>>     cfe/trunk/lib/Serialization/ModuleManager.cpp
>>>
>>> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=220493&r1=220492&r2=220493&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
>>> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Thu Oct 23
>>> 13:05:36 2014
>>> @@ -288,7 +288,10 @@ namespace clang {
>>>
>>>        /// \brief Record code for the module map file that was used to
>>> build this
>>>        /// AST file.
>>> -      MODULE_MAP_FILE = 14
>>> +      MODULE_MAP_FILE = 14,
>>> +
>>> +      /// \brief Record code for the signature that identifiers this
>>> AST file.
>>> +      SIGNATURE = 15
>>>      };
>>>
>>>      /// \brief Record types that occur within the input-files block
>>>
>>> Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=220493&r1=220492&r2=220493&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
>>> +++ cfe/trunk/include/clang/Serialization/ASTReader.h Thu Oct 23
>>> 13:05:36 2014
>>> @@ -1125,6 +1125,7 @@ private:
>>>                              SourceLocation ImportLoc, ModuleFile
>>> *ImportedBy,
>>>                              SmallVectorImpl<ImportedModule> &Loaded,
>>>                              off_t ExpectedSize, time_t ExpectedModTime,
>>> +                            serialization::ASTFileSignature
>>> ExpectedSignature,
>>>                              unsigned ClientLoadCapabilities);
>>>    ASTReadResult ReadControlBlock(ModuleFile &F,
>>>                                   SmallVectorImpl<ImportedModule>
>>> &Loaded,
>>>
>>> Modified: cfe/trunk/include/clang/Serialization/Module.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/Module.h?rev=220493&r1=220492&r2=220493&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/Serialization/Module.h (original)
>>> +++ cfe/trunk/include/clang/Serialization/Module.h Thu Oct 23 13:05:36
>>> 2014
>>> @@ -97,6 +97,8 @@ public:
>>>    bool isNotFound() const { return Val.getInt() == NotFound; }
>>>  };
>>>
>>> +typedef unsigned ASTFileSignature;
>>> +
>>>  /// \brief Information about a module that has been loaded by the
>>> ASTReader.
>>>  ///
>>>  /// Each instance of the Module class corresponds to a single AST file,
>>> which
>>> @@ -152,6 +154,10 @@ public:
>>>    /// \brief The file entry for the module file.
>>>    const FileEntry *File;
>>>
>>> +  /// \brief The signature of the module file, which may be used along
>>> with size
>>> +  /// and modification time to identify this particular file.
>>> +  ASTFileSignature Signature;
>>> +
>>>    /// \brief Whether this module has been directly imported by the
>>>    /// user.
>>>    bool DirectlyImported;
>>>
>>> Modified: cfe/trunk/include/clang/Serialization/ModuleManager.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ModuleManager.h?rev=220493&r1=220492&r2=220493&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/Serialization/ModuleManager.h (original)
>>> +++ cfe/trunk/include/clang/Serialization/ModuleManager.h Thu Oct 23
>>> 13:05:36 2014
>>> @@ -179,6 +179,12 @@ public:
>>>    /// \param ExpectedModTime The expected modification time of the
>>> module
>>>    /// file, used for validation. This will be zero if unknown.
>>>    ///
>>> +  /// \param ExpectedSignature The expected signature of the module
>>> file, used
>>> +  /// for validation. This will be zero if unknown.
>>> +  ///
>>> +  /// \param ReadSignature Reads the signature from an AST file without
>>> actually
>>> +  /// loading it.
>>> +  ///
>>>    /// \param Module A pointer to the module file if the module was
>>> successfully
>>>    /// loaded.
>>>    ///
>>> @@ -191,6 +197,9 @@ public:
>>>                              SourceLocation ImportLoc,
>>>                              ModuleFile *ImportedBy, unsigned Generation,
>>>                              off_t ExpectedSize, time_t ExpectedModTime,
>>> +                            ASTFileSignature ExpectedSignature,
>>> +
>>> std::function<ASTFileSignature(llvm::BitstreamReader &)>
>>> +                                ReadSignature,
>>>                              ModuleFile *&Module,
>>>                              std::string &ErrorStr);
>>>
>>>
>>> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=220493&r1=220492&r2=220493&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
>>> +++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Oct 23 13:05:36 2014
>>> @@ -2363,6 +2363,11 @@ ASTReader::ReadControlBlock(ModuleFile &
>>>        break;
>>>      }
>>>
>>> +    case SIGNATURE:
>>> +      assert((!F.Signature || F.Signature == Record[0]) && "signature
>>> changed");
>>> +      F.Signature = Record[0];
>>> +      break;
>>> +
>>>      case IMPORTS: {
>>>        // Load each of the imported PCH files.
>>>        unsigned Idx = 0, N = Record.size();
>>> @@ -2376,6 +2381,7 @@ ASTReader::ReadControlBlock(ModuleFile &
>>>              SourceLocation::getFromRawEncoding(Record[Idx++]);
>>>          off_t StoredSize = (off_t)Record[Idx++];
>>>          time_t StoredModTime = (time_t)Record[Idx++];
>>> +        ASTFileSignature StoredSignature = Record[Idx++];
>>>          unsigned Length = Record[Idx++];
>>>          SmallString<128> ImportedFile(Record.begin() + Idx,
>>>                                        Record.begin() + Idx + Length);
>>> @@ -2383,7 +2389,7 @@ ASTReader::ReadControlBlock(ModuleFile &
>>>
>>>          // Load the AST file.
>>>          switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F,
>>> Loaded,
>>> -                           StoredSize, StoredModTime,
>>> +                           StoredSize, StoredModTime, StoredSignature,
>>>                             ClientLoadCapabilities)) {
>>>          case Failure: return Failure;
>>>            // If we have to ignore the dependency, we'll have to ignore
>>> this too.
>>> @@ -3552,7 +3558,7 @@ ASTReader::ASTReadResult ASTReader::Read
>>>    SmallVector<ImportedModule, 4> Loaded;
>>>    switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type,
>>> ImportLoc,
>>>                                                  /*ImportedBy=*/nullptr,
>>> Loaded,
>>> -                                                0, 0,
>>> +                                                0, 0, 0,
>>>
>>>  ClientLoadCapabilities)) {
>>>    case Failure:
>>>    case Missing:
>>> @@ -3719,6 +3725,8 @@ ASTReader::ASTReadResult ASTReader::Read
>>>    return Success;
>>>  }
>>>
>>> +static ASTFileSignature readASTFileSignature(llvm::BitstreamReader
>>> &StreamFile);
>>> +
>>>  ASTReader::ASTReadResult
>>>  ASTReader::ReadASTCore(StringRef FileName,
>>>                         ModuleKind Type,
>>> @@ -3726,12 +3734,14 @@ ASTReader::ReadASTCore(StringRef FileNam
>>>                         ModuleFile *ImportedBy,
>>>                         SmallVectorImpl<ImportedModule> &Loaded,
>>>                         off_t ExpectedSize, time_t ExpectedModTime,
>>> +                       ASTFileSignature ExpectedSignature,
>>>                         unsigned ClientLoadCapabilities) {
>>>    ModuleFile *M;
>>>    std::string ErrorStr;
>>>    ModuleManager::AddModuleResult AddResult
>>>      = ModuleMgr.addModule(FileName, Type, ImportLoc, ImportedBy,
>>>                            getGeneration(), ExpectedSize,
>>> ExpectedModTime,
>>> +                          ExpectedSignature, readASTFileSignature,
>>>                            M, ErrorStr);
>>>
>>>    switch (AddResult) {
>>> @@ -4029,6 +4039,34 @@ static bool SkipCursorToBlock(BitstreamC
>>>    }
>>>  }
>>>
>>> +static ASTFileSignature readASTFileSignature(llvm::BitstreamReader
>>> &StreamFile){
>>> +  BitstreamCursor Stream(StreamFile);
>>> +  if (Stream.Read(8) != 'C' ||
>>> +      Stream.Read(8) != 'P' ||
>>> +      Stream.Read(8) != 'C' ||
>>> +      Stream.Read(8) != 'H') {
>>> +    return 0;
>>> +  }
>>> +
>>> +  // Scan for the CONTROL_BLOCK_ID block.
>>> +  if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID))
>>> +    return 0;
>>> +
>>> +  // Scan for SIGNATURE inside the control block.
>>> +  ASTReader::RecordData Record;
>>> +  while (1) {
>>> +    llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
>>> +    if (Entry.Kind == llvm::BitstreamEntry::EndBlock ||
>>> +        Entry.Kind != llvm::BitstreamEntry::Record)
>>> +      return 0;
>>> +
>>> +    Record.clear();
>>> +    StringRef Blob;
>>> +    if (SIGNATURE == Stream.readRecord(Entry.ID, Record, &Blob))
>>> +      return Record[0];
>>> +  }
>>> +}
>>> +
>>>  /// \brief Retrieve the name of the original source file name
>>>  /// directly from the AST file, without actually loading the AST
>>>  /// file.
>>>
>>> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=220493&r1=220492&r2=220493&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
>>> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu Oct 23 13:05:36 2014
>>> @@ -51,6 +51,7 @@
>>>  #include "llvm/Support/MemoryBuffer.h"
>>>  #include "llvm/Support/OnDiskHashTable.h"
>>>  #include "llvm/Support/Path.h"
>>> +#include "llvm/Support/Process.h"
>>>  #include <algorithm>
>>>  #include <cstdio>
>>>  #include <string.h>
>>> @@ -862,6 +863,7 @@ void ASTWriter::WriteBlockInfoBlock() {
>>>    // Control Block.
>>>    BLOCK(CONTROL_BLOCK);
>>>    RECORD(METADATA);
>>> +  RECORD(SIGNATURE);
>>>    RECORD(MODULE_NAME);
>>>    RECORD(MODULE_MAP_FILE);
>>>    RECORD(IMPORTS);
>>> @@ -1092,6 +1094,14 @@ adjustFilenameForRelocatablePCH(const ch
>>>    return Filename + Pos;
>>>  }
>>>
>>> +static ASTFileSignature getSignature() {
>>> +  while (1) {
>>> +    if (ASTFileSignature S = llvm::sys::Process::GetRandomNumber())
>>> +      return S;
>>> +    // Rely on GetRandomNumber to eventually return non-zero...
>>> +  }
>>> +}
>>> +
>>>  /// \brief Write the control block.
>>>  void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
>>>                                    StringRef isysroot,
>>> @@ -1121,6 +1131,11 @@ void ASTWriter::WriteControlBlock(Prepro
>>>    Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
>>>                              getClangFullRepositoryVersion());
>>>
>>> +  // Signature
>>> +  Record.clear();
>>> +  Record.push_back(getSignature());
>>> +  Stream.EmitRecord(SIGNATURE, Record);
>>> +
>>>    // Module name
>>>    if (WritingModule) {
>>>      BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
>>> @@ -1173,6 +1188,7 @@ void ASTWriter::WriteControlBlock(Prepro
>>>        AddSourceLocation((*M)->ImportLoc, Record);
>>>        Record.push_back((*M)->File->getSize());
>>>        Record.push_back((*M)->File->getModificationTime());
>>> +      Record.push_back((*M)->Signature);
>>>        const std::string &FileName = (*M)->FileName;
>>>        Record.push_back(FileName.size());
>>>        Record.append(FileName.begin(), FileName.end());
>>>
>>> Modified: cfe/trunk/lib/Serialization/GlobalModuleIndex.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/GlobalModuleIndex.cpp?rev=220493&r1=220492&r2=220493&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Serialization/GlobalModuleIndex.cpp (original)
>>> +++ cfe/trunk/lib/Serialization/GlobalModuleIndex.cpp Thu Oct 23
>>> 13:05:36 2014
>>> @@ -591,6 +591,10 @@ bool GlobalModuleIndexBuilder::loadModul
>>>          off_t StoredSize = (off_t)Record[Idx++];
>>>          time_t StoredModTime = (time_t)Record[Idx++];
>>>
>>> +        // Skip the stored signature.
>>> +        // FIXME: we could read the signature out of the import and
>>> validate it.
>>> +        Idx++;
>>> +
>>>          // Retrieve the imported file name.
>>>          unsigned Length = Record[Idx++];
>>>          SmallString<128> ImportedFile(Record.begin() + Idx,
>>>
>>> Modified: cfe/trunk/lib/Serialization/Module.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/Module.cpp?rev=220493&r1=220492&r2=220493&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Serialization/Module.cpp (original)
>>> +++ cfe/trunk/lib/Serialization/Module.cpp Thu Oct 23 13:05:36 2014
>>> @@ -21,7 +21,7 @@ using namespace serialization;
>>>  using namespace reader;
>>>
>>>  ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation)
>>> -  : Kind(Kind), File(nullptr), DirectlyImported(false),
>>> +  : Kind(Kind), File(nullptr), Signature(0), DirectlyImported(false),
>>>      Generation(Generation), SizeInBits(0),
>>>      LocalNumSLocEntries(0), SLocEntryBaseID(0),
>>>      SLocEntryBaseOffset(0), SLocEntryOffsets(nullptr),
>>>
>>> Modified: cfe/trunk/lib/Serialization/ModuleManager.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ModuleManager.cpp?rev=220493&r1=220492&r2=220493&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Serialization/ModuleManager.cpp (original)
>>> +++ cfe/trunk/lib/Serialization/ModuleManager.cpp Thu Oct 23 13:05:36
>>> 2014
>>> @@ -57,6 +57,9 @@ ModuleManager::addModule(StringRef FileN
>>>                           SourceLocation ImportLoc, ModuleFile
>>> *ImportedBy,
>>>                           unsigned Generation,
>>>                           off_t ExpectedSize, time_t ExpectedModTime,
>>> +                         ASTFileSignature ExpectedSignature,
>>> +
>>>  std::function<ASTFileSignature(llvm::BitstreamReader &)>
>>> +                             ReadSignature,
>>>                           ModuleFile *&Module,
>>>                           std::string &ErrorStr) {
>>>    Module = nullptr;
>>> @@ -130,6 +133,21 @@ ModuleManager::addModule(StringRef FileN
>>>      // Initialize the stream
>>>      New->StreamFile.init((const unsigned char
>>> *)New->Buffer->getBufferStart(),
>>>                           (const unsigned char
>>> *)New->Buffer->getBufferEnd());
>>> +
>>> +    if (ExpectedSignature) {
>>> +      New->Signature = ReadSignature(New->StreamFile);
>>> +      if (New->Signature != ExpectedSignature) {
>>> +        ErrorStr = New->Signature ? "signature mismatch"
>>> +                                  : "could not read module signature";
>>> +
>>> +        // Remove the module file immediately, since removeModules
>>> might try to
>>> +        // invalidate the file cache for Entry, and that is not safe if
>>> this
>>> +        // module is *itself* up to date, but has an out-of-date
>>> importer.
>>> +        Modules.erase(Entry);
>>> +        Chain.pop_back();
>>> +        return OutOfDate;
>>> +      }
>>> +    }
>>>    }
>>>
>>>    if (ImportedBy) {
>>>
>>> Added: cfe/trunk/test/Modules/rebuild.m
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/rebuild.m?rev=220493&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/test/Modules/rebuild.m (added)
>>> +++ cfe/trunk/test/Modules/rebuild.m Thu Oct 23 13:05:36 2014
>>> @@ -0,0 +1,29 @@
>>> +// REQUIRES: shell
>>> +// RUN: rm -rf %t
>>> +
>>> +// Build Module and set its timestamp
>>> +// RUN: echo '@import Module;' | %clang_cc1 -fmodules
>>> -fmodules-cache-path=%t -fdisable-module-hash -fsyntax-only -F %S/Inputs -x
>>> objective-c -
>>> +// RUN: touch -m -a -t 201101010000 %t/Module.pcm
>>> +// RUN: cp %t/Module.pcm %t/Module.pcm.saved
>>> +// RUN: wc -c %t/Module.pcm > %t/Module.size.saved
>>> +
>>> +// Build DependsOnModule
>>> +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t
>>> -fdisable-module-hash -fsyntax-only -F %S/Inputs %s
>>> +// RUN: diff %t/Module.pcm %t/Module.pcm.saved
>>> +// RUN: cp %t/DependsOnModule.pcm %t/DependsOnModule.pcm.saved
>>> +
>>> +// Rebuild Module, reset its timestamp, and verify its size hasn't
>>> changed
>>> +// RUN: rm %t/Module.pcm
>>> +// RUN: echo '@import Module;' | %clang_cc1 -fmodules
>>> -fmodules-cache-path=%t -fdisable-module-hash -fsyntax-only -F %S/Inputs -x
>>> objective-c -
>>> +// RUN: touch -m -a -t 201101010000 %t/Module.pcm
>>> +// RUN: wc -c %t/Module.pcm > %t/Module.size
>>> +// RUN: diff %t/Module.size %t/Module.size.saved
>>> +// RUN: cp %t/Module.pcm %t/Module.pcm.saved.2
>>> +
>>> +// But the signature at least is expected to change, so we rebuild
>>> DependsOnModule.
>>> +// NOTE: if we change how the signature is created, this test may need
>>> updating.
>>> +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t
>>> -fdisable-module-hash -fsyntax-only -F %S/Inputs %s
>>> +// RUN: diff %t/Module.pcm %t/Module.pcm.saved.2
>>> +// RUN: not diff %t/DependsOnModule.pcm %t/DependsOnModule.pcm.saved
>>> +
>>> + at import DependsOnModule;
>>>
>>>
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>>
>>
>>
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20141023/7b8b1162/attachment.html>


More information about the cfe-commits mailing list