Exemple #1
0
static Optional<std::pair<llvm::APSInt, Type>>
  getIntegerConstantForMacroToken(ClangImporter::Implementation &impl,
                                  DeclContext *DC,
                                  const clang::Token &token) {

  // Integer literal.
  if (token.is(clang::tok::numeric_constant)) {
    if (auto literal = parseNumericLiteral<clang::IntegerLiteral>(impl,token)) {
      auto value = llvm::APSInt { literal->getValue(),
                                  literal->getType()->isUnsignedIntegerType() };
      auto type  = impl.importType(literal->getType(),
                                   ImportTypeKind::Value,
                                   isInSystemModule(DC),
                                   Bridgeability::None);
      return {{ value, type }};
    }

  // Macro identifier.
  } else if (token.is(clang::tok::identifier) &&
             token.getIdentifierInfo()->hasMacroDefinition()) {

    auto rawID = token.getIdentifierInfo();
    auto definition = impl.getClangPreprocessor().getMacroDefinition(rawID);
    if (!definition)
      return None;

    ClangNode macroNode;
    const clang::MacroInfo *macroInfo;
    if (definition.getModuleMacros().empty()) {
      macroInfo = definition.getMacroInfo();
      macroNode = macroInfo;
    } else {
      // Follow MacroDefinition::getMacroInfo in preferring the last ModuleMacro
      // rather than the first.
      const clang::ModuleMacro *moduleMacro =
          definition.getModuleMacros().back();
      macroInfo = moduleMacro->getMacroInfo();
      macroNode = moduleMacro;
    }
    auto importedID = impl.getNameImporter().importMacroName(rawID, macroInfo);
    (void)impl.importMacro(importedID, macroNode);

    auto searcher = impl.ImportedMacroConstants.find(macroInfo);
    if (searcher == impl.ImportedMacroConstants.end()) {
      return None;
    }
    auto importedConstant = searcher->second;
    if (!importedConstant.first.isInt()) {
      return None;
    }
    return {{ importedConstant.first.getInt(), importedConstant.second }};
  }

  return None;
}
bool PragmaRecorder::GetPragmaNameFromToken(const clang::Token &Token,
        std::string &PragmaName) {
    if (Token.isLiteral())
        PragmaName.assign(Token.getLiteralData(), Token.getLength());
    else if (Token.is(clang::tok::identifier))
        PragmaName.assign(Token.getIdentifierInfo()->getNameStart(),
                          Token.getIdentifierInfo()->getLength());
    else
        return false;
    return true;
}
void PreprocessingRecord::InclusionDirective(SourceLocation HashLoc,
                                             const clang::Token &IncludeTok, 
                                             llvm::StringRef FileName, 
                                             bool IsAngled, 
                                             const FileEntry *File,
                                           clang::SourceLocation EndLoc) {
  InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
  
  switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
  case tok::pp_include: 
    Kind = InclusionDirective::Include; 
    break;
    
  case tok::pp_import: 
    Kind = InclusionDirective::Import; 
    break;
    
  case tok::pp_include_next: 
    Kind = InclusionDirective::IncludeNext; 
    break;
    
  case tok::pp___include_macros: 
    Kind = InclusionDirective::IncludeMacros;
    break;
    
  default:
    llvm_unreachable("Unknown include directive kind");
    return;
  }
  
  clang::InclusionDirective *ID
    = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, 
                                            File, SourceRange(HashLoc, EndLoc));
  PreprocessedEntities.push_back(ID);
}
	void FMacroCallback::MacroExpands(const clang::Token &MacroNameTok, const clang::MacroDirective *MD, clang::SourceRange Range, const clang::MacroArgs *Args)
	{
		auto MacroName = MacroNameTok.getIdentifierInfo()->getName();
		if (IsBuiltInMacro(MD) || IsMacroDefinedInCommandLine(MacroName) || IsPredefinedMacro(MacroName))
		{
			return;
		}

		if (MacroDefinitionToFile.Contains(FString(MacroName.data())))
		{
			auto MacroDefinitionFilename = FString(*MacroDefinitionToFile[MacroName.data()]);
			MacroDefinitionFilename.ReplaceInline(TEXT("\\"), TEXT("/"));
			auto MacroDefinitionFilenameHash = FIncludeSetMapKeyFuncs::GetKeyHash(MacroDefinitionFilename);

			auto MacroExpansionFilename = FString(SourceManager.getFilename(Range.getBegin()).data());
			MacroExpansionFilename.ReplaceInline(TEXT("\\"), TEXT("/"));
			auto MacroExpansionFilenameHash = FIncludeSetMapKeyFuncs::GetKeyHash(MacroExpansionFilename);

			if (!Includes.Contains(MacroExpansionFilenameHash))
			{
				Includes.FindOrAdd(MacroExpansionFilenameHash).Add(MacroDefinitionFilenameHash);
			}

			GHashToFilename.Add(MacroDefinitionFilenameHash, MacroDefinitionFilename);
			GHashToFilename.Add(MacroExpansionFilenameHash, MacroExpansionFilename);

			return;
		}
		
		OutputFileContents.Logf(TEXT("Internal error. Found usage of unknown macro %s."), ANSI_TO_TCHAR(MacroName.data()));
	}
Exemple #5
0
static best_guess tok_type(clang::Preprocessor &pp, const char *macro_name,
                           const clang::Token &t, StringSet *seen) {
    using namespace clang;
    tok::TokenKind k = t.getKind();

    if(k == tok::identifier) {
        IdentifierInfo *ii = t.getIdentifierInfo();
        if(ii && !seen->count(ii->getNameStart()))
            return macro_type(pp, ii->getNameStart(),
                              pp.getMacroInfo(ii), seen);

        return tok_ok;
    }

    if (k == tok::l_paren || k == tok::r_paren || k == tok::amp || k == tok::plus ||
        k == tok::star || k == tok::minus || k == tok::tilde || k == tok::slash ||
        k == tok::percent || k == tok::lessless || k == tok::greatergreater ||
        k == tok::caret || k == tok::pipe || k == tok::exclaim ||
        k == tok::kw_int || k == tok::kw_float || k == tok::kw_double ||
        k == tok::kw_long || k == tok::kw_signed || k == tok::kw_unsigned)

        return tok_ok;

    return tok_invalid;
}
void PreprocessorCallback::Defined(const clang::Token& MacroNameTok, MyMacroDefinition MD,
                                   clang::SourceRange Range)
{
    clang::SourceLocation loc = MacroNameTok.getLocation();
    if (!loc.isValid() || !loc.isFileID())
        return;

    clang::SourceManager &sm = annotator.getSourceMgr();

    clang::FileID FID = sm.getFileID(loc);
    if (!annotator.shouldProcess(FID))
        return;

    std::string ref = llvm::Twine("_M/", MacroNameTok.getIdentifierInfo()->getName()).str();
    std::string link;
    std::string dataProj;
    clang::SourceLocation defLoc;
    clang::FileID defFID;

    if (MD) {
#if CLANG_VERSION_MAJOR == 3 && CLANG_VERSION_MINOR >= 7
        auto *MI = MD.getMacroInfo();
#else
        auto *MI = MD->getMacroInfo();
#endif
        if (MI) {
            defLoc = MI->getDefinitionLoc();
            defFID = sm.getFileID(defLoc);
        }
    }

    if (defFID.isInvalid() || defFID != FID) {
        if (!defFID.isInvalid()) {
            link = annotator.pathTo(FID, defFID, &dataProj);
        }
        if (link.empty()) {
            std::string tag = "class=\"macro\" data-ref=\"" % ref % "\"";
            annotator.generator(FID).addTag("span", tag, sm.getFileOffset(loc), MacroNameTok.getLength());
            return;
        }

        if (!dataProj.empty()) {
            dataProj = " data-proj=\"" % dataProj % "\"";
        }
    }

    if (sm.getMainFileID() != defFID) {
        annotator.registerMacro(ref, MacroNameTok.getLocation(), Annotator::Use_Address);
    }

    std::string tag = "class=\"macro\" href=\"" % link % "#" % llvm::Twine(sm.getExpansionLineNumber(defLoc)).str()
        % "\" data-ref=\"" % ref % "\"" % dataProj;
    annotator.generator(FID).addTag("a", tag, sm.getFileOffset(loc), MacroNameTok.getLength());
}
Exemple #7
0
static Optional<std::pair<llvm::APSInt, Type>>
  getIntegerConstantForMacroToken(ClangImporter::Implementation &impl,
                                  DeclContext *DC,
                                  const clang::Token &token) {

  // Integer literal.
  if (token.is(clang::tok::numeric_constant)) {
    if (auto literal = parseNumericLiteral<clang::IntegerLiteral>(impl,token)) {
      auto value = llvm::APSInt { literal->getValue(),
                                  literal->getType()->isUnsignedIntegerType() };
      auto type  = impl.importType(literal->getType(),
                                   ImportTypeKind::Value,
                                   isInSystemModule(DC),
                                   /*isFullyBridgeable*/false);
      return {{ value, type }};
    }

  // Macro identifier.
  } else if (token.is(clang::tok::identifier) &&
             token.getIdentifierInfo()->hasMacroDefinition()) {

    auto rawID      = token.getIdentifierInfo();
    auto macroInfo  = impl.getClangPreprocessor().getMacroInfo(rawID);
    auto importedID = impl.getNameImporter().importMacroName(rawID, macroInfo);
    impl.importMacro(importedID, macroInfo);

    auto searcher = impl.ImportedMacroConstants.find(macroInfo);
    if (searcher == impl.ImportedMacroConstants.end()) {
      return None;
    }
    auto importedConstant = searcher->second;
    if (!importedConstant.first.isInt()) {
      return None;
    }
    return {{ importedConstant.first.getInt(), importedConstant.second }};
  }

  return None;
}
Exemple #8
0
void PreprocessingRecord::InclusionDirective(
    SourceLocation HashLoc,
    const clang::Token &IncludeTok,
    StringRef FileName,
    bool IsAngled,
    CharSourceRange FilenameRange,
    const FileEntry *File,
    StringRef SearchPath,
    StringRef RelativePath,
    const Module *Imported) {
  InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
  
  switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
  case tok::pp_include: 
    Kind = InclusionDirective::Include; 
    break;
    
  case tok::pp_import: 
    Kind = InclusionDirective::Import; 
    break;

  case tok::pp_using: 
    Kind = InclusionDirective::Using;
    break;
    
  case tok::pp_include_next: 
    Kind = InclusionDirective::IncludeNext; 
    break;
    
  case tok::pp___include_macros: 
    Kind = InclusionDirective::IncludeMacros;
    break;
    
  default:
    llvm_unreachable("Unknown include directive kind");
  }

  SourceLocation EndLoc;
  if (!IsAngled) {
    EndLoc = FilenameRange.getBegin();
  } else {
    EndLoc = FilenameRange.getEnd();
    if (FilenameRange.isCharRange())
      EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects
                                            // a token range.
  }
  clang::InclusionDirective *ID
    = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, 
                                            File, SourceRange(HashLoc, EndLoc));
  addPreprocessedEntity(ID);
}
	void FMacroCallback::MacroDefined(const clang::Token &MacroNameTok, const clang::MacroDirective *MD)
	{
		auto MacroName = MacroNameTok.getIdentifierInfo()->getName();

		if (IsMacroDefinedInCommandLine(MacroName) || IsBuiltInMacro(MD) || IsPredefinedMacro(MacroName))
		{
			return;
		}

		auto MacroDefinitionFile = FString(SourceManager.getFilename(MacroNameTok.getLocation()).data());
		MacroDefinitionFile.ReplaceInline(TEXT("\\"), TEXT("/"));
		if (MacroDefinitionFile.IsEmpty())
		{
			OutputFileContents.Logf(TEXT("Found unexpected definition of macro %s."), ANSI_TO_TCHAR(MacroName.data()));
		}
		MacroDefinitionToFile.Add(MacroName.data(), MacroDefinitionFile);
	}
void PreprocessorCallback::MacroDefined(const clang::Token& MacroNameTok, const clang::MacroDirective *MD)
{
    clang::SourceLocation loc = MacroNameTok.getLocation();
    if (!loc.isValid() || !loc.isFileID())
        return;

    clang::SourceManager &sm = annotator.getSourceMgr();
    clang::FileID FID = sm.getFileID(loc);
    if (!annotator.shouldProcess(FID))
        return;

    std::string ref = llvm::Twine("_M/", MacroNameTok.getIdentifierInfo()->getName()).str();

    if (sm.getMainFileID() != FID) {
        annotator.registerMacro(ref, MacroNameTok.getLocation(), Annotator::Declaration);
    }

    annotator.generator(FID).addTag("dfn", "class=\"macro\" id=\""% ref %"\" data-ref=\"" % ref % "\"", sm.getFileOffset(loc), MacroNameTok.getLength());
}
Exemple #11
0
 void DeclCollector::MacroDefined(const clang::Token &MacroNameTok,
                                  const clang::MacroDirective *MD) {
   Transaction::MacroDirectiveInfo MDE(MacroNameTok.getIdentifierInfo(), MD);
   m_CurTransaction->append(MDE);
 }
void PreprocessorCallback::MacroExpands(const clang::Token& MacroNameTok,
                                        MyMacroDefinition MD,
                                        clang::SourceRange Range, const clang::MacroArgs *)
{
    if (disabled)
        return;

#if CLANG_VERSION_MAJOR == 3 && CLANG_VERSION_MINOR >= 7
    auto *MI = MD.getMacroInfo();
#else
    auto *MI = MD->getMacroInfo();
#endif
    clang::SourceLocation loc = MacroNameTok.getLocation();
    if (!loc.isValid() || !loc.isFileID())
        return;
    clang::SourceManager &sm = annotator.getSourceMgr();
    clang::FileID FID = sm.getFileID(loc);
    if (!annotator.shouldProcess(FID))
        return;

    const char *begin = sm.getCharacterData(Range.getBegin());
    int len = sm.getCharacterData(Range.getEnd()) - begin;
    len += clang::Lexer::MeasureTokenLength(Range.getEnd(), sm, PP.getLangOpts());

    std::string copy(begin, len);
    begin = copy.c_str();
    clang::Lexer lex(loc, PP.getLangOpts(), begin, begin, begin + len);
    std::vector<clang::Token> tokens;
    std::string expansion;

    //Lousely based on code from clang::html::HighlightMacros

    // Lex all the tokens in raw mode, to avoid entering #includes or expanding
    // macros.
    clang::Token tok;
    do {
        lex.LexFromRawLexer(tok);

        // If this is a # at the start of a line, discard it from the token stream.
        // We don't want the re-preprocess step to see #defines, #includes or other
        // preprocessor directives.
        if (tok.is(clang::tok::hash) && tok.isAtStartOfLine())
            continue;

        // If this is a ## token, change its kind to unknown so that repreprocessing
        // it will not produce an error.
        if (tok.is(clang::tok::hashhash))
            tok.setKind(clang::tok::unknown);

        // If this raw token is an identifier, the raw lexer won't have looked up
        // the corresponding identifier info for it.  Do this now so that it will be
        // macro expanded when we re-preprocess it.
        if (tok.is(clang::tok::raw_identifier))
            PP.LookUpIdentifierInfo(tok);

        tokens.push_back(tok);

    } while(!tok.is(clang::tok::eof));

    // Temporarily change the diagnostics object so that we ignore any generated
    // diagnostics from this pass.
    clang::DiagnosticsEngine TmpDiags(PP.getDiagnostics().getDiagnosticIDs(),
                                      &PP.getDiagnostics().getDiagnosticOptions(),
                                      new clang::IgnoringDiagConsumer);

    disabled = true;
    clang::DiagnosticsEngine *OldDiags = &PP.getDiagnostics();
    PP.setDiagnostics(TmpDiags);

    // We don't want pragmas either. Although we filtered out #pragma, removing
    // _Pragma and __pragma is much harder.
    bool pragmasPreviouslyEnabled = PP.getPragmasEnabled();
    PP.setPragmasEnabled(false);

    PP.EnterTokenStream(tokens.data(), tokens.size(), false, false);

    PP.Lex(tok);
    while(tok.isNot(clang::tok::eof)) {
        // If the tokens were already space separated, or if they must be to avoid
        // them being implicitly pasted, add a space between them.
        if (tok.hasLeadingSpace())
            expansion += ' ';
           // ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok)) //FIXME
        // Escape any special characters in the token text.
        expansion += PP.getSpelling(tok);
        PP.Lex(tok);
    }

    PP.setDiagnostics(*OldDiags);
    PP.setPragmasEnabled(pragmasPreviouslyEnabled);
    disabled = false;

    std::string ref = llvm::Twine("_M/", MacroNameTok.getIdentifierInfo()->getName()).str();

    clang::SourceLocation defLoc = MI->getDefinitionLoc();
    clang::FileID defFID = sm.getFileID(defLoc);
    llvm::SmallString<128> expansionBuffer;
    std::string link;
    std::string dataProj;
    if (defFID != FID) {
        link = annotator.pathTo(FID, defFID, &dataProj);
        if (link.empty()) {
            std::string tag = "class=\"macro\" title=\"" % Generator::escapeAttr(expansion, expansionBuffer)
                % "\" data-ref=\"" % ref % "\"";
            annotator.generator(FID).addTag("span", tag, sm.getFileOffset(loc), MacroNameTok.getLength());
            return;
        }

        if (!dataProj.empty()) {
            dataProj = " data-proj=\"" % dataProj % "\"";
        }
    }

    if (sm.getMainFileID() != defFID) {
        annotator.registerMacro(ref, MacroNameTok.getLocation(), Annotator::Use_Call);
    }

    std::string tag = "class=\"macro\" href=\"" % link % "#" % llvm::Twine(sm.getExpansionLineNumber(defLoc)).str()
        % "\" title=\"" % Generator::escapeAttr(expansion, expansionBuffer)
        % "\" data-ref=\"" % ref % "\"" % dataProj;
    annotator.generator(FID).addTag("a", tag, sm.getFileOffset(loc), MacroNameTok.getLength());
}