Assert in SourceManager::getFileIDSlow()

Hi,

My code is triggering the assert:

  assert(SLocOffset && "Invalid FileID");

In SourceManager::getFileIDSlow().

It happens as a result of calling SM->isFromMainFile(Loc) in some
ASTConsumer code that looks like:

void HandleTopLevelDecl(clang::DeclGroupRef D) {
  for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
    if (clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I)) {
      clang::SourceLocation Loc = FD->getTypeSpecStartLoc();
      if (SM->isFromMainFile(Loc)) {
        // ...
      }
    }
  }
}

(The input that is being parsed begins with a function declaration.)

I am not sure how old this issue is, but it makes ccons unusable
(which is quite a shame, since I hoped ccons could work fine with the
clang 1.0 release). Any advice would be appreciated.

-Alexei

Some more details:

The input being parsed doesn't have to start with a function
declaration to trigger this assert.

Also, removing the assert in question makes ccons work correctly. Any
chance this could be fixed?

(If it could also be added to the clang 1.0 branch, that would be
really appreciated.)

Thanks! (Patch is attached.)

-Alexei

sm_assert_fix.diff (626 Bytes)

Some more details:

The input being parsed doesn't have to start with a function
declaration to trigger this assert.

Also, removing the assert in question makes ccons work correctly. Any
chance this could be fixed?

(If it could also be added to the clang 1.0 branch, that would be
really appreciated.)

Thanks! (Patch is attached.)

Alexei, I don't follow why this is safe or how you're triggering it. The SourceManager sets up the "Source Location namespace" very carefully and "0" is not a valid "offset". 0 is a sentinel that indicates a default constructed source location. I think you need to change your client to something like this:

     clang::SourceLocation Loc = FD->getTypeSpecStartLoc();
     if (Loc.isValid() && SM->isFromMainFile(Loc)) {

-Chris

Why would FD->getTypeSpecStartLoc() be invalid?

-Alexei

Why would FD->getTypeSpecStartLoc() be invalid?

Maybe FD is synthesized? I don't know, what does the ast dump show for the decl?

-Chris

When I parse input that consists of simply "#include <stdio.h>" on Mac
OS X 10.5.7, I get an invalid FD->getTypeSpecStartLoc() for "long
ftell(FILE *)".

-Alexei

Does the same issue occur for a file containing just "typedef struct
FILE FILE; long ftell(FILE*);"? If no, does the same issue occur if
you send the pre-processed input through clang? If yes, can you
reduce it with delta (http://delta.tigris.org/)?

-Eli

Does the same issue occur for a file containing just "typedef struct
FILE FILE; long ftell(FILE*);"?

Yes it does.

-Alexei

Hi Alexei,

Fixed it in r80448.

-Argiris