ParsedAST TestTU::build() const { std::string FullFilename = testPath(Filename), FullHeaderName = testPath(HeaderFilename); std::vector<const char *> Cmd = {"clang", FullFilename.c_str()}; // FIXME: this shouldn't need to be conditional, but it breaks a // GoToDefinition test for some reason (getMacroArgExpandedLocation fails). if (!HeaderCode.empty()) { Cmd.push_back("-include"); Cmd.push_back(FullHeaderName.c_str()); } Cmd.insert(Cmd.end(), ExtraArgs.begin(), ExtraArgs.end()); ParseInputs Inputs; Inputs.CompileCommand.Filename = FullFilename; Inputs.CompileCommand.CommandLine = {Cmd.begin(), Cmd.end()}; Inputs.CompileCommand.Directory = testRoot(); Inputs.Contents = Code; Inputs.FS = buildTestFS({{FullFilename, Code}, {FullHeaderName, HeaderCode}}); Inputs.Opts = ParseOptions(); Inputs.Opts.ClangTidyOpts.Checks = ClangTidyChecks; Inputs.Index = ExternalIndex; if (Inputs.Index) Inputs.Opts.SuggestMissingIncludes = true; auto CI = buildCompilerInvocation(Inputs); assert(CI && "Failed to build compilation invocation."); auto Preamble = buildPreamble(FullFilename, *CI, /*OldPreamble=*/nullptr, /*OldCompileCommand=*/Inputs.CompileCommand, Inputs, /*StoreInMemory=*/true, /*PreambleCallback=*/nullptr); auto AST = buildAST(FullFilename, createInvocationFromCommandLine(Cmd), Inputs, Preamble); if (!AST.hasValue()) { ADD_FAILURE() << "Failed to build code:\n" << Code; llvm_unreachable("Failed to build TestTU!"); } return std::move(*AST); }
/* * buildDefinition */ static void buildDefinition(char * pzDef, char const * pzFile, int line, char * pzOut) { static char const zSrcFile[] = " %s = '%s';\n"; static char const zLineNum[] = " %s = '%d';\n"; ag_bool these_are_global_defs; tSuccess preamble; int re_res; char* pzNextDef = NULL; regmatch_t match[2]; if (*pzDef == '*') { these_are_global_defs = AG_TRUE; strcpy(pzOut, zGlobal); pzOut += sizeof(zGlobal)-1; pzOut += sprintf(pzOut, zLineId, line, pzFile); pzDef = strchr(pzDef, '\n'); preamble = PROBLEM; } else { these_are_global_defs = AG_FALSE; preamble = buildPreamble(&pzDef, &pzOut, pzFile, line); if (FAILED(preamble)) { *pzOut = NUL; return; } } /* * FOR each attribute for this entry, ... */ for (;;) { /* * Find the next attribute regular expression */ re_res = regexec(&attrib_re, pzDef, COUNT(match), match, 0); switch (re_res) { case 0: /* * NUL-terminate the current attribute. * Set the "next" pointer to the start of the next attribute name. */ pzDef[ match[0].rm_so ] = NUL; if (pzNextDef != NULL) pzOut = emitDefinition(pzNextDef, pzOut); pzNextDef = pzDef = pzDef + match[1].rm_so; break; case REG_NOMATCH: /* * No more attributes. */ if (pzNextDef == NULL) { *pzOut++ = '\n'; *pzOut++ = '#'; sprintf(pzOut, zNoData, pzFile, line); fputs(pzOut, stderr); pzOut += strlen(pzOut); return; } pzOut = emitDefinition(pzNextDef, pzOut); goto eachAttrDone; break; default: { char zRER[ MAXNAMELEN ]; static char const zErr[] = "error %d (%s) finding `%s' in\n%s\n\n"; regerror(re_res, &attrib_re, zRER, sizeof(zRER)); *pzOut++ = '\n'; *pzOut++ = '#'; sprintf(pzOut, zErr, re_res, zRER, zAttribRe, pzDef); fprintf(stderr, "getdefs: %s", zErr); return; } } } eachAttrDone:; if (these_are_global_defs) { *pzOut = NUL; return; } if (HAVE_OPT(COMMON_ASSIGN)) { int ct = STACKCT_OPT(COMMON_ASSIGN); char const ** ppz = STACKLST_OPT(COMMON_ASSIGN); do { pzOut += sprintf(pzOut, " %s;\n", *ppz++); } while (--ct > 0); } if (HAVE_OPT(SRCFILE)) pzOut += sprintf(pzOut, zSrcFile, OPT_ARG(SRCFILE), pzFile); if (HAVE_OPT(LINENUM)) pzOut += sprintf(pzOut, zLineNum, OPT_ARG(LINENUM), line); /* * IF the preamble had a problem, it is because it could not * emit the final "#endif\n" directive. Do that now. */ if (HADGLITCH(preamble)) strcpy(pzOut, "};\n#endif\n"); else strcpy(pzOut, "};\n"); }