1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459 |
- /* c-index-test.c */
- #include "clang/Config/config.h"
- #include "clang-c/Index.h"
- #include "clang-c/CXCompilationDatabase.h"
- #include "clang-c/BuildSystem.h"
- #include "clang-c/Documentation.h"
- #include <ctype.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <assert.h>
- #ifdef CLANG_HAVE_LIBXML
- #include <libxml/parser.h>
- #include <libxml/relaxng.h>
- #include <libxml/xmlerror.h>
- #endif
- #ifdef _WIN32
- # include <direct.h>
- #else
- # include <unistd.h>
- #endif
- extern int indextest_core_main(int argc, const char **argv);
- /******************************************************************************/
- /* Utility functions. */
- /******************************************************************************/
- #ifdef _MSC_VER
- char *basename(const char* path)
- {
- char* base1 = (char*)strrchr(path, '/');
- char* base2 = (char*)strrchr(path, '\\');
- if (base1 && base2)
- return((base1 > base2) ? base1 + 1 : base2 + 1);
- else if (base1)
- return(base1 + 1);
- else if (base2)
- return(base2 + 1);
- return((char*)path);
- }
- char *dirname(char* path)
- {
- char* base1 = (char*)strrchr(path, '/');
- char* base2 = (char*)strrchr(path, '\\');
- if (base1 && base2)
- if (base1 > base2)
- *base1 = 0;
- else
- *base2 = 0;
- else if (base1)
- *base1 = 0;
- else if (base2)
- *base2 = 0;
- return path;
- }
- #else
- extern char *basename(const char *);
- extern char *dirname(char *);
- #endif
- /** \brief Return the default parsing options. */
- static unsigned getDefaultParsingOptions() {
- unsigned options = CXTranslationUnit_DetailedPreprocessingRecord;
- if (getenv("CINDEXTEST_EDITING"))
- options |= clang_defaultEditingTranslationUnitOptions();
- if (getenv("CINDEXTEST_COMPLETION_CACHING"))
- options |= CXTranslationUnit_CacheCompletionResults;
- if (getenv("CINDEXTEST_COMPLETION_NO_CACHING"))
- options &= ~CXTranslationUnit_CacheCompletionResults;
- if (getenv("CINDEXTEST_SKIP_FUNCTION_BODIES"))
- options |= CXTranslationUnit_SkipFunctionBodies;
- if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS"))
- options |= CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
- if (getenv("CINDEXTEST_CREATE_PREAMBLE_ON_FIRST_PARSE"))
- options |= CXTranslationUnit_CreatePreambleOnFirstParse;
- if (getenv("CINDEXTEST_KEEP_GOING"))
- options |= CXTranslationUnit_KeepGoing;
- return options;
- }
- /** \brief Returns 0 in case of success, non-zero in case of a failure. */
- static int checkForErrors(CXTranslationUnit TU);
- static void describeLibclangFailure(enum CXErrorCode Err) {
- switch (Err) {
- case CXError_Success:
- fprintf(stderr, "Success\n");
- return;
- case CXError_Failure:
- fprintf(stderr, "Failure (no details available)\n");
- return;
- case CXError_Crashed:
- fprintf(stderr, "Failure: libclang crashed\n");
- return;
- case CXError_InvalidArguments:
- fprintf(stderr, "Failure: invalid arguments passed to a libclang routine\n");
- return;
- case CXError_ASTReadError:
- fprintf(stderr, "Failure: AST deserialization error occurred\n");
- return;
- }
- }
- static void PrintExtent(FILE *out, unsigned begin_line, unsigned begin_column,
- unsigned end_line, unsigned end_column) {
- fprintf(out, "[%d:%d - %d:%d]", begin_line, begin_column,
- end_line, end_column);
- }
- static unsigned CreateTranslationUnit(CXIndex Idx, const char *file,
- CXTranslationUnit *TU) {
- enum CXErrorCode Err = clang_createTranslationUnit2(Idx, file, TU);
- if (Err != CXError_Success) {
- fprintf(stderr, "Unable to load translation unit from '%s'!\n", file);
- describeLibclangFailure(Err);
- *TU = 0;
- return 0;
- }
- return 1;
- }
- void free_remapped_files(struct CXUnsavedFile *unsaved_files,
- int num_unsaved_files) {
- int i;
- for (i = 0; i != num_unsaved_files; ++i) {
- free((char *)unsaved_files[i].Filename);
- free((char *)unsaved_files[i].Contents);
- }
- free(unsaved_files);
- }
- static int parse_remapped_files_with_opt(const char *opt_name,
- int argc, const char **argv,
- int start_arg,
- struct CXUnsavedFile **unsaved_files,
- int *num_unsaved_files) {
- int i;
- int arg;
- int prefix_len = strlen(opt_name);
- int arg_indices[20];
- *unsaved_files = 0;
- *num_unsaved_files = 0;
- /* Count the number of remapped files. */
- for (arg = start_arg; arg < argc; ++arg) {
- if (strncmp(argv[arg], opt_name, prefix_len))
- continue;
- assert(*num_unsaved_files < (int)(sizeof(arg_indices)/sizeof(int)));
- arg_indices[*num_unsaved_files] = arg;
- ++*num_unsaved_files;
- }
- if (*num_unsaved_files == 0)
- return 0;
- *unsaved_files
- = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) *
- *num_unsaved_files);
- for (i = 0; i != *num_unsaved_files; ++i) {
- struct CXUnsavedFile *unsaved = *unsaved_files + i;
- const char *arg_string = argv[arg_indices[i]] + prefix_len;
- int filename_len;
- char *filename;
- char *contents;
- FILE *to_file;
- const char *sep = strchr(arg_string, ',');
- if (!sep) {
- fprintf(stderr,
- "error: %sfrom:to argument is missing comma\n", opt_name);
- free_remapped_files(*unsaved_files, i);
- *unsaved_files = 0;
- *num_unsaved_files = 0;
- return -1;
- }
- /* Open the file that we're remapping to. */
- to_file = fopen(sep + 1, "rb");
- if (!to_file) {
- fprintf(stderr, "error: cannot open file %s that we are remapping to\n",
- sep + 1);
- free_remapped_files(*unsaved_files, i);
- *unsaved_files = 0;
- *num_unsaved_files = 0;
- return -1;
- }
- /* Determine the length of the file we're remapping to. */
- fseek(to_file, 0, SEEK_END);
- unsaved->Length = ftell(to_file);
- fseek(to_file, 0, SEEK_SET);
- /* Read the contents of the file we're remapping to. */
- contents = (char *)malloc(unsaved->Length + 1);
- if (fread(contents, 1, unsaved->Length, to_file) != unsaved->Length) {
- fprintf(stderr, "error: unexpected %s reading 'to' file %s\n",
- (feof(to_file) ? "EOF" : "error"), sep + 1);
- fclose(to_file);
- free_remapped_files(*unsaved_files, i);
- free(contents);
- *unsaved_files = 0;
- *num_unsaved_files = 0;
- return -1;
- }
- contents[unsaved->Length] = 0;
- unsaved->Contents = contents;
- /* Close the file. */
- fclose(to_file);
- /* Copy the file name that we're remapping from. */
- filename_len = sep - arg_string;
- filename = (char *)malloc(filename_len + 1);
- memcpy(filename, arg_string, filename_len);
- filename[filename_len] = 0;
- unsaved->Filename = filename;
- }
- return 0;
- }
- static int parse_remapped_files(int argc, const char **argv, int start_arg,
- struct CXUnsavedFile **unsaved_files,
- int *num_unsaved_files) {
- return parse_remapped_files_with_opt("-remap-file=", argc, argv, start_arg,
- unsaved_files, num_unsaved_files);
- }
- static int parse_remapped_files_with_try(int try_idx,
- int argc, const char **argv,
- int start_arg,
- struct CXUnsavedFile **unsaved_files,
- int *num_unsaved_files) {
- struct CXUnsavedFile *unsaved_files_no_try_idx;
- int num_unsaved_files_no_try_idx;
- struct CXUnsavedFile *unsaved_files_try_idx;
- int num_unsaved_files_try_idx;
- int ret;
- char opt_name[32];
- ret = parse_remapped_files(argc, argv, start_arg,
- &unsaved_files_no_try_idx, &num_unsaved_files_no_try_idx);
- if (ret)
- return ret;
- sprintf(opt_name, "-remap-file-%d=", try_idx);
- ret = parse_remapped_files_with_opt(opt_name, argc, argv, start_arg,
- &unsaved_files_try_idx, &num_unsaved_files_try_idx);
- if (ret)
- return ret;
- if (num_unsaved_files_no_try_idx == 0) {
- *unsaved_files = unsaved_files_try_idx;
- *num_unsaved_files = num_unsaved_files_try_idx;
- return 0;
- }
- if (num_unsaved_files_try_idx == 0) {
- *unsaved_files = unsaved_files_no_try_idx;
- *num_unsaved_files = num_unsaved_files_no_try_idx;
- return 0;
- }
- *num_unsaved_files = num_unsaved_files_no_try_idx + num_unsaved_files_try_idx;
- *unsaved_files
- = (struct CXUnsavedFile *)realloc(unsaved_files_no_try_idx,
- sizeof(struct CXUnsavedFile) *
- *num_unsaved_files);
- memcpy(*unsaved_files + num_unsaved_files_no_try_idx,
- unsaved_files_try_idx, sizeof(struct CXUnsavedFile) *
- num_unsaved_files_try_idx);
- free(unsaved_files_try_idx);
- return 0;
- }
- static const char *parse_comments_schema(int argc, const char **argv) {
- const char *CommentsSchemaArg = "-comments-xml-schema=";
- const char *CommentSchemaFile = NULL;
- if (argc == 0)
- return CommentSchemaFile;
- if (!strncmp(argv[0], CommentsSchemaArg, strlen(CommentsSchemaArg)))
- CommentSchemaFile = argv[0] + strlen(CommentsSchemaArg);
- return CommentSchemaFile;
- }
- /******************************************************************************/
- /* Pretty-printing. */
- /******************************************************************************/
- static const char *FileCheckPrefix = "CHECK";
- static void PrintCString(const char *CStr) {
- if (CStr != NULL && CStr[0] != '\0') {
- for ( ; *CStr; ++CStr) {
- const char C = *CStr;
- switch (C) {
- case '\n': printf("\\n"); break;
- case '\r': printf("\\r"); break;
- case '\t': printf("\\t"); break;
- case '\v': printf("\\v"); break;
- case '\f': printf("\\f"); break;
- default: putchar(C); break;
- }
- }
- }
- }
- static void PrintCStringWithPrefix(const char *Prefix, const char *CStr) {
- printf(" %s=[", Prefix);
- PrintCString(CStr);
- printf("]");
- }
- static void PrintCXStringAndDispose(CXString Str) {
- PrintCString(clang_getCString(Str));
- clang_disposeString(Str);
- }
- static void PrintCXStringWithPrefix(const char *Prefix, CXString Str) {
- PrintCStringWithPrefix(Prefix, clang_getCString(Str));
- }
- static void PrintCXStringWithPrefixAndDispose(const char *Prefix,
- CXString Str) {
- PrintCStringWithPrefix(Prefix, clang_getCString(Str));
- clang_disposeString(Str);
- }
- static void PrintRange(CXSourceRange R, const char *str) {
- CXFile begin_file, end_file;
- unsigned begin_line, begin_column, end_line, end_column;
- clang_getSpellingLocation(clang_getRangeStart(R),
- &begin_file, &begin_line, &begin_column, 0);
- clang_getSpellingLocation(clang_getRangeEnd(R),
- &end_file, &end_line, &end_column, 0);
- if (!begin_file || !end_file)
- return;
- if (str)
- printf(" %s=", str);
- PrintExtent(stdout, begin_line, begin_column, end_line, end_column);
- }
- int want_display_name = 0;
- static void printVersion(const char *Prefix, CXVersion Version) {
- if (Version.Major < 0)
- return;
- printf("%s%d", Prefix, Version.Major);
-
- if (Version.Minor < 0)
- return;
- printf(".%d", Version.Minor);
- if (Version.Subminor < 0)
- return;
- printf(".%d", Version.Subminor);
- }
- struct CommentASTDumpingContext {
- int IndentLevel;
- };
- static void DumpCXCommentInternal(struct CommentASTDumpingContext *Ctx,
- CXComment Comment) {
- unsigned i;
- unsigned e;
- enum CXCommentKind Kind = clang_Comment_getKind(Comment);
- Ctx->IndentLevel++;
- for (i = 0, e = Ctx->IndentLevel; i != e; ++i)
- printf(" ");
- printf("(");
- switch (Kind) {
- case CXComment_Null:
- printf("CXComment_Null");
- break;
- case CXComment_Text:
- printf("CXComment_Text");
- PrintCXStringWithPrefixAndDispose("Text",
- clang_TextComment_getText(Comment));
- if (clang_Comment_isWhitespace(Comment))
- printf(" IsWhitespace");
- if (clang_InlineContentComment_hasTrailingNewline(Comment))
- printf(" HasTrailingNewline");
- break;
- case CXComment_InlineCommand:
- printf("CXComment_InlineCommand");
- PrintCXStringWithPrefixAndDispose(
- "CommandName",
- clang_InlineCommandComment_getCommandName(Comment));
- switch (clang_InlineCommandComment_getRenderKind(Comment)) {
- case CXCommentInlineCommandRenderKind_Normal:
- printf(" RenderNormal");
- break;
- case CXCommentInlineCommandRenderKind_Bold:
- printf(" RenderBold");
- break;
- case CXCommentInlineCommandRenderKind_Monospaced:
- printf(" RenderMonospaced");
- break;
- case CXCommentInlineCommandRenderKind_Emphasized:
- printf(" RenderEmphasized");
- break;
- }
- for (i = 0, e = clang_InlineCommandComment_getNumArgs(Comment);
- i != e; ++i) {
- printf(" Arg[%u]=", i);
- PrintCXStringAndDispose(
- clang_InlineCommandComment_getArgText(Comment, i));
- }
- if (clang_InlineContentComment_hasTrailingNewline(Comment))
- printf(" HasTrailingNewline");
- break;
- case CXComment_HTMLStartTag: {
- unsigned NumAttrs;
- printf("CXComment_HTMLStartTag");
- PrintCXStringWithPrefixAndDispose(
- "Name",
- clang_HTMLTagComment_getTagName(Comment));
- NumAttrs = clang_HTMLStartTag_getNumAttrs(Comment);
- if (NumAttrs != 0) {
- printf(" Attrs:");
- for (i = 0; i != NumAttrs; ++i) {
- printf(" ");
- PrintCXStringAndDispose(clang_HTMLStartTag_getAttrName(Comment, i));
- printf("=");
- PrintCXStringAndDispose(clang_HTMLStartTag_getAttrValue(Comment, i));
- }
- }
- if (clang_HTMLStartTagComment_isSelfClosing(Comment))
- printf(" SelfClosing");
- if (clang_InlineContentComment_hasTrailingNewline(Comment))
- printf(" HasTrailingNewline");
- break;
- }
- case CXComment_HTMLEndTag:
- printf("CXComment_HTMLEndTag");
- PrintCXStringWithPrefixAndDispose(
- "Name",
- clang_HTMLTagComment_getTagName(Comment));
- if (clang_InlineContentComment_hasTrailingNewline(Comment))
- printf(" HasTrailingNewline");
- break;
- case CXComment_Paragraph:
- printf("CXComment_Paragraph");
- if (clang_Comment_isWhitespace(Comment))
- printf(" IsWhitespace");
- break;
- case CXComment_BlockCommand:
- printf("CXComment_BlockCommand");
- PrintCXStringWithPrefixAndDispose(
- "CommandName",
- clang_BlockCommandComment_getCommandName(Comment));
- for (i = 0, e = clang_BlockCommandComment_getNumArgs(Comment);
- i != e; ++i) {
- printf(" Arg[%u]=", i);
- PrintCXStringAndDispose(
- clang_BlockCommandComment_getArgText(Comment, i));
- }
- break;
- case CXComment_ParamCommand:
- printf("CXComment_ParamCommand");
- switch (clang_ParamCommandComment_getDirection(Comment)) {
- case CXCommentParamPassDirection_In:
- printf(" in");
- break;
- case CXCommentParamPassDirection_Out:
- printf(" out");
- break;
- case CXCommentParamPassDirection_InOut:
- printf(" in,out");
- break;
- }
- if (clang_ParamCommandComment_isDirectionExplicit(Comment))
- printf(" explicitly");
- else
- printf(" implicitly");
- PrintCXStringWithPrefixAndDispose(
- "ParamName",
- clang_ParamCommandComment_getParamName(Comment));
- if (clang_ParamCommandComment_isParamIndexValid(Comment))
- printf(" ParamIndex=%u", clang_ParamCommandComment_getParamIndex(Comment));
- else
- printf(" ParamIndex=Invalid");
- break;
- case CXComment_TParamCommand:
- printf("CXComment_TParamCommand");
- PrintCXStringWithPrefixAndDispose(
- "ParamName",
- clang_TParamCommandComment_getParamName(Comment));
- if (clang_TParamCommandComment_isParamPositionValid(Comment)) {
- printf(" ParamPosition={");
- for (i = 0, e = clang_TParamCommandComment_getDepth(Comment);
- i != e; ++i) {
- printf("%u", clang_TParamCommandComment_getIndex(Comment, i));
- if (i != e - 1)
- printf(", ");
- }
- printf("}");
- } else
- printf(" ParamPosition=Invalid");
- break;
- case CXComment_VerbatimBlockCommand:
- printf("CXComment_VerbatimBlockCommand");
- PrintCXStringWithPrefixAndDispose(
- "CommandName",
- clang_BlockCommandComment_getCommandName(Comment));
- break;
- case CXComment_VerbatimBlockLine:
- printf("CXComment_VerbatimBlockLine");
- PrintCXStringWithPrefixAndDispose(
- "Text",
- clang_VerbatimBlockLineComment_getText(Comment));
- break;
- case CXComment_VerbatimLine:
- printf("CXComment_VerbatimLine");
- PrintCXStringWithPrefixAndDispose(
- "Text",
- clang_VerbatimLineComment_getText(Comment));
- break;
- case CXComment_FullComment:
- printf("CXComment_FullComment");
- break;
- }
- if (Kind != CXComment_Null) {
- const unsigned NumChildren = clang_Comment_getNumChildren(Comment);
- unsigned i;
- for (i = 0; i != NumChildren; ++i) {
- printf("\n// %s: ", FileCheckPrefix);
- DumpCXCommentInternal(Ctx, clang_Comment_getChild(Comment, i));
- }
- }
- printf(")");
- Ctx->IndentLevel--;
- }
- static void DumpCXComment(CXComment Comment) {
- struct CommentASTDumpingContext Ctx;
- Ctx.IndentLevel = 1;
- printf("\n// %s: CommentAST=[\n// %s:", FileCheckPrefix, FileCheckPrefix);
- DumpCXCommentInternal(&Ctx, Comment);
- printf("]");
- }
- static void ValidateCommentXML(const char *Str, const char *CommentSchemaFile) {
- #ifdef CLANG_HAVE_LIBXML
- xmlRelaxNGParserCtxtPtr RNGParser;
- xmlRelaxNGPtr Schema;
- xmlDocPtr Doc;
- xmlRelaxNGValidCtxtPtr ValidationCtxt;
- int status;
- if (!CommentSchemaFile)
- return;
- RNGParser = xmlRelaxNGNewParserCtxt(CommentSchemaFile);
- if (!RNGParser) {
- printf(" libXMLError");
- return;
- }
- Schema = xmlRelaxNGParse(RNGParser);
- Doc = xmlParseDoc((const xmlChar *) Str);
- if (!Doc) {
- xmlErrorPtr Error = xmlGetLastError();
- printf(" CommentXMLInvalid [not well-formed XML: %s]", Error->message);
- return;
- }
- ValidationCtxt = xmlRelaxNGNewValidCtxt(Schema);
- status = xmlRelaxNGValidateDoc(ValidationCtxt, Doc);
- if (!status)
- printf(" CommentXMLValid");
- else if (status > 0) {
- xmlErrorPtr Error = xmlGetLastError();
- printf(" CommentXMLInvalid [not vaild XML: %s]", Error->message);
- } else
- printf(" libXMLError");
- xmlRelaxNGFreeValidCtxt(ValidationCtxt);
- xmlFreeDoc(Doc);
- xmlRelaxNGFree(Schema);
- xmlRelaxNGFreeParserCtxt(RNGParser);
- #endif
- }
- static void PrintCursorComments(CXCursor Cursor,
- const char *CommentSchemaFile) {
- {
- CXString RawComment;
- const char *RawCommentCString;
- CXString BriefComment;
- const char *BriefCommentCString;
- RawComment = clang_Cursor_getRawCommentText(Cursor);
- RawCommentCString = clang_getCString(RawComment);
- if (RawCommentCString != NULL && RawCommentCString[0] != '\0') {
- PrintCStringWithPrefix("RawComment", RawCommentCString);
- PrintRange(clang_Cursor_getCommentRange(Cursor), "RawCommentRange");
- BriefComment = clang_Cursor_getBriefCommentText(Cursor);
- BriefCommentCString = clang_getCString(BriefComment);
- if (BriefCommentCString != NULL && BriefCommentCString[0] != '\0')
- PrintCStringWithPrefix("BriefComment", BriefCommentCString);
- clang_disposeString(BriefComment);
- }
- clang_disposeString(RawComment);
- }
- {
- CXComment Comment = clang_Cursor_getParsedComment(Cursor);
- if (clang_Comment_getKind(Comment) != CXComment_Null) {
- PrintCXStringWithPrefixAndDispose("FullCommentAsHTML",
- clang_FullComment_getAsHTML(Comment));
- {
- CXString XML;
- XML = clang_FullComment_getAsXML(Comment);
- PrintCXStringWithPrefix("FullCommentAsXML", XML);
- ValidateCommentXML(clang_getCString(XML), CommentSchemaFile);
- clang_disposeString(XML);
- }
- DumpCXComment(Comment);
- }
- }
- }
- typedef struct {
- unsigned line;
- unsigned col;
- } LineCol;
- static int lineCol_cmp(const void *p1, const void *p2) {
- const LineCol *lhs = p1;
- const LineCol *rhs = p2;
- if (lhs->line != rhs->line)
- return (int)lhs->line - (int)rhs->line;
- return (int)lhs->col - (int)rhs->col;
- }
- static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
- CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
- if (clang_isInvalid(Cursor.kind)) {
- CXString ks = clang_getCursorKindSpelling(Cursor.kind);
- printf("Invalid Cursor => %s", clang_getCString(ks));
- clang_disposeString(ks);
- }
- else {
- CXString string, ks;
- CXCursor Referenced;
- unsigned line, column;
- CXCursor SpecializationOf;
- CXCursor *overridden;
- unsigned num_overridden;
- unsigned RefNameRangeNr;
- CXSourceRange CursorExtent;
- CXSourceRange RefNameRange;
- int AlwaysUnavailable;
- int AlwaysDeprecated;
- CXString UnavailableMessage;
- CXString DeprecatedMessage;
- CXPlatformAvailability PlatformAvailability[2];
- int NumPlatformAvailability;
- int I;
- ks = clang_getCursorKindSpelling(Cursor.kind);
- string = want_display_name? clang_getCursorDisplayName(Cursor)
- : clang_getCursorSpelling(Cursor);
- printf("%s=%s", clang_getCString(ks),
- clang_getCString(string));
- clang_disposeString(ks);
- clang_disposeString(string);
- Referenced = clang_getCursorReferenced(Cursor);
- if (!clang_equalCursors(Referenced, clang_getNullCursor())) {
- if (clang_getCursorKind(Referenced) == CXCursor_OverloadedDeclRef) {
- unsigned I, N = clang_getNumOverloadedDecls(Referenced);
- printf("[");
- for (I = 0; I != N; ++I) {
- CXCursor Ovl = clang_getOverloadedDecl(Referenced, I);
- CXSourceLocation Loc;
- if (I)
- printf(", ");
-
- Loc = clang_getCursorLocation(Ovl);
- clang_getSpellingLocation(Loc, 0, &line, &column, 0);
- printf("%d:%d", line, column);
- }
- printf("]");
- } else {
- CXSourceLocation Loc = clang_getCursorLocation(Referenced);
- clang_getSpellingLocation(Loc, 0, &line, &column, 0);
- printf(":%d:%d", line, column);
- }
- }
- if (clang_isCursorDefinition(Cursor))
- printf(" (Definition)");
-
- switch (clang_getCursorAvailability(Cursor)) {
- case CXAvailability_Available:
- break;
-
- case CXAvailability_Deprecated:
- printf(" (deprecated)");
- break;
-
- case CXAvailability_NotAvailable:
- printf(" (unavailable)");
- break;
- case CXAvailability_NotAccessible:
- printf(" (inaccessible)");
- break;
- }
-
- NumPlatformAvailability
- = clang_getCursorPlatformAvailability(Cursor,
- &AlwaysDeprecated,
- &DeprecatedMessage,
- &AlwaysUnavailable,
- &UnavailableMessage,
- PlatformAvailability, 2);
- if (AlwaysUnavailable) {
- printf(" (always unavailable: \"%s\")",
- clang_getCString(UnavailableMessage));
- } else if (AlwaysDeprecated) {
- printf(" (always deprecated: \"%s\")",
- clang_getCString(DeprecatedMessage));
- } else {
- for (I = 0; I != NumPlatformAvailability; ++I) {
- if (I >= 2)
- break;
-
- printf(" (%s", clang_getCString(PlatformAvailability[I].Platform));
- if (PlatformAvailability[I].Unavailable)
- printf(", unavailable");
- else {
- printVersion(", introduced=", PlatformAvailability[I].Introduced);
- printVersion(", deprecated=", PlatformAvailability[I].Deprecated);
- printVersion(", obsoleted=", PlatformAvailability[I].Obsoleted);
- }
- if (clang_getCString(PlatformAvailability[I].Message)[0])
- printf(", message=\"%s\"",
- clang_getCString(PlatformAvailability[I].Message));
- printf(")");
- }
- }
- for (I = 0; I != NumPlatformAvailability; ++I) {
- if (I >= 2)
- break;
- clang_disposeCXPlatformAvailability(PlatformAvailability + I);
- }
-
- clang_disposeString(DeprecatedMessage);
- clang_disposeString(UnavailableMessage);
-
- if (clang_CXXField_isMutable(Cursor))
- printf(" (mutable)");
- if (clang_CXXMethod_isStatic(Cursor))
- printf(" (static)");
- if (clang_CXXMethod_isVirtual(Cursor))
- printf(" (virtual)");
- if (clang_CXXMethod_isConst(Cursor))
- printf(" (const)");
- if (clang_CXXMethod_isPureVirtual(Cursor))
- printf(" (pure)");
- if (clang_Cursor_isVariadic(Cursor))
- printf(" (variadic)");
- if (clang_Cursor_isObjCOptional(Cursor))
- printf(" (@optional)");
- if (Cursor.kind == CXCursor_IBOutletCollectionAttr) {
- CXType T =
- clang_getCanonicalType(clang_getIBOutletCollectionType(Cursor));
- CXString S = clang_getTypeKindSpelling(T.kind);
- printf(" [IBOutletCollection=%s]", clang_getCString(S));
- clang_disposeString(S);
- }
-
- if (Cursor.kind == CXCursor_CXXBaseSpecifier) {
- enum CX_CXXAccessSpecifier access = clang_getCXXAccessSpecifier(Cursor);
- unsigned isVirtual = clang_isVirtualBase(Cursor);
- const char *accessStr = 0;
- switch (access) {
- case CX_CXXInvalidAccessSpecifier:
- accessStr = "invalid"; break;
- case CX_CXXPublic:
- accessStr = "public"; break;
- case CX_CXXProtected:
- accessStr = "protected"; break;
- case CX_CXXPrivate:
- accessStr = "private"; break;
- }
-
- printf(" [access=%s isVirtual=%s]", accessStr,
- isVirtual ? "true" : "false");
- }
- SpecializationOf = clang_getSpecializedCursorTemplate(Cursor);
- if (!clang_equalCursors(SpecializationOf, clang_getNullCursor())) {
- CXSourceLocation Loc = clang_getCursorLocation(SpecializationOf);
- CXString Name = clang_getCursorSpelling(SpecializationOf);
- clang_getSpellingLocation(Loc, 0, &line, &column, 0);
- printf(" [Specialization of %s:%d:%d]",
- clang_getCString(Name), line, column);
- clang_disposeString(Name);
- if (Cursor.kind == CXCursor_FunctionDecl) {
- /* Collect the template parameter kinds from the base template. */
- unsigned NumTemplateArgs = clang_Cursor_getNumTemplateArguments(Cursor);
- unsigned I;
- for (I = 0; I < NumTemplateArgs; I++) {
- enum CXTemplateArgumentKind TAK =
- clang_Cursor_getTemplateArgumentKind(Cursor, I);
- switch(TAK) {
- case CXTemplateArgumentKind_Type:
- {
- CXType T = clang_Cursor_getTemplateArgumentType(Cursor, I);
- CXString S = clang_getTypeSpelling(T);
- printf(" [Template arg %d: kind: %d, type: %s]",
- I, TAK, clang_getCString(S));
- clang_disposeString(S);
- }
- break;
- case CXTemplateArgumentKind_Integral:
- printf(" [Template arg %d: kind: %d, intval: %lld]",
- I, TAK, clang_Cursor_getTemplateArgumentValue(Cursor, I));
- break;
- default:
- printf(" [Template arg %d: kind: %d]\n", I, TAK);
- }
- }
- }
- }
- clang_getOverriddenCursors(Cursor, &overridden, &num_overridden);
- if (num_overridden) {
- unsigned I;
- LineCol lineCols[50];
- assert(num_overridden <= 50);
- printf(" [Overrides ");
- for (I = 0; I != num_overridden; ++I) {
- CXSourceLocation Loc = clang_getCursorLocation(overridden[I]);
- clang_getSpellingLocation(Loc, 0, &line, &column, 0);
- lineCols[I].line = line;
- lineCols[I].col = column;
- }
- /* Make the order of the override list deterministic. */
- qsort(lineCols, num_overridden, sizeof(LineCol), lineCol_cmp);
- for (I = 0; I != num_overridden; ++I) {
- if (I)
- printf(", ");
- printf("@%d:%d", lineCols[I].line, lineCols[I].col);
- }
- printf("]");
- clang_disposeOverriddenCursors(overridden);
- }
-
- if (Cursor.kind == CXCursor_InclusionDirective) {
- CXFile File = clang_getIncludedFile(Cursor);
- CXString Included = clang_getFileName(File);
- printf(" (%s)", clang_getCString(Included));
- clang_disposeString(Included);
-
- if (clang_isFileMultipleIncludeGuarded(TU, File))
- printf(" [multi-include guarded]");
- }
-
- CursorExtent = clang_getCursorExtent(Cursor);
- RefNameRange = clang_getCursorReferenceNameRange(Cursor,
- CXNameRange_WantQualifier
- | CXNameRange_WantSinglePiece
- | CXNameRange_WantTemplateArgs,
- 0);
- if (!clang_equalRanges(CursorExtent, RefNameRange))
- PrintRange(RefNameRange, "SingleRefName");
-
- for (RefNameRangeNr = 0; 1; RefNameRangeNr++) {
- RefNameRange = clang_getCursorReferenceNameRange(Cursor,
- CXNameRange_WantQualifier
- | CXNameRange_WantTemplateArgs,
- RefNameRangeNr);
- if (clang_equalRanges(clang_getNullRange(), RefNameRange))
- break;
- if (!clang_equalRanges(CursorExtent, RefNameRange))
- PrintRange(RefNameRange, "RefName");
- }
- PrintCursorComments(Cursor, CommentSchemaFile);
- {
- unsigned PropAttrs = clang_Cursor_getObjCPropertyAttributes(Cursor, 0);
- if (PropAttrs != CXObjCPropertyAttr_noattr) {
- printf(" [");
- #define PRINT_PROP_ATTR(A) \
- if (PropAttrs & CXObjCPropertyAttr_##A) printf(#A ",")
- PRINT_PROP_ATTR(readonly);
- PRINT_PROP_ATTR(getter);
- PRINT_PROP_ATTR(assign);
- PRINT_PROP_ATTR(readwrite);
- PRINT_PROP_ATTR(retain);
- PRINT_PROP_ATTR(copy);
- PRINT_PROP_ATTR(nonatomic);
- PRINT_PROP_ATTR(setter);
- PRINT_PROP_ATTR(atomic);
- PRINT_PROP_ATTR(weak);
- PRINT_PROP_ATTR(strong);
- PRINT_PROP_ATTR(unsafe_unretained);
- printf("]");
- }
- }
- {
- unsigned QT = clang_Cursor_getObjCDeclQualifiers(Cursor);
- if (QT != CXObjCDeclQualifier_None) {
- printf(" [");
- #define PRINT_OBJC_QUAL(A) \
- if (QT & CXObjCDeclQualifier_##A) printf(#A ",")
- PRINT_OBJC_QUAL(In);
- PRINT_OBJC_QUAL(Inout);
- PRINT_OBJC_QUAL(Out);
- PRINT_OBJC_QUAL(Bycopy);
- PRINT_OBJC_QUAL(Byref);
- PRINT_OBJC_QUAL(Oneway);
- printf("]");
- }
- }
- }
- }
- static const char* GetCursorSource(CXCursor Cursor) {
- CXSourceLocation Loc = clang_getCursorLocation(Cursor);
- CXString source;
- CXFile file;
- clang_getExpansionLocation(Loc, &file, 0, 0, 0);
- source = clang_getFileName(file);
- if (!clang_getCString(source)) {
- clang_disposeString(source);
- return "<invalid loc>";
- }
- else {
- const char *b = basename(clang_getCString(source));
- clang_disposeString(source);
- return b;
- }
- }
- /******************************************************************************/
- /* Callbacks. */
- /******************************************************************************/
- typedef void (*PostVisitTU)(CXTranslationUnit);
- void PrintDiagnostic(CXDiagnostic Diagnostic) {
- FILE *out = stderr;
- CXFile file;
- CXString Msg;
- unsigned display_opts = CXDiagnostic_DisplaySourceLocation
- | CXDiagnostic_DisplayColumn | CXDiagnostic_DisplaySourceRanges
- | CXDiagnostic_DisplayOption;
- unsigned i, num_fixits;
- if (clang_getDiagnosticSeverity(Diagnostic) == CXDiagnostic_Ignored)
- return;
- Msg = clang_formatDiagnostic(Diagnostic, display_opts);
- fprintf(stderr, "%s\n", clang_getCString(Msg));
- clang_disposeString(Msg);
- clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
- &file, 0, 0, 0);
- if (!file)
- return;
- num_fixits = clang_getDiagnosticNumFixIts(Diagnostic);
- fprintf(stderr, "Number FIX-ITs = %d\n", num_fixits);
- for (i = 0; i != num_fixits; ++i) {
- CXSourceRange range;
- CXString insertion_text = clang_getDiagnosticFixIt(Diagnostic, i, &range);
- CXSourceLocation start = clang_getRangeStart(range);
- CXSourceLocation end = clang_getRangeEnd(range);
- unsigned start_line, start_column, end_line, end_column;
- CXFile start_file, end_file;
- clang_getSpellingLocation(start, &start_file, &start_line,
- &start_column, 0);
- clang_getSpellingLocation(end, &end_file, &end_line, &end_column, 0);
- if (clang_equalLocations(start, end)) {
- /* Insertion. */
- if (start_file == file)
- fprintf(out, "FIX-IT: Insert \"%s\" at %d:%d\n",
- clang_getCString(insertion_text), start_line, start_column);
- } else if (strcmp(clang_getCString(insertion_text), "") == 0) {
- /* Removal. */
- if (start_file == file && end_file == file) {
- fprintf(out, "FIX-IT: Remove ");
- PrintExtent(out, start_line, start_column, end_line, end_column);
- fprintf(out, "\n");
- }
- } else {
- /* Replacement. */
- if (start_file == end_file) {
- fprintf(out, "FIX-IT: Replace ");
- PrintExtent(out, start_line, start_column, end_line, end_column);
- fprintf(out, " with \"%s\"\n", clang_getCString(insertion_text));
- }
- }
- clang_disposeString(insertion_text);
- }
- }
- void PrintDiagnosticSet(CXDiagnosticSet Set) {
- int i = 0, n = clang_getNumDiagnosticsInSet(Set);
- for ( ; i != n ; ++i) {
- CXDiagnostic Diag = clang_getDiagnosticInSet(Set, i);
- CXDiagnosticSet ChildDiags = clang_getChildDiagnostics(Diag);
- PrintDiagnostic(Diag);
- if (ChildDiags)
- PrintDiagnosticSet(ChildDiags);
- }
- }
- void PrintDiagnostics(CXTranslationUnit TU) {
- CXDiagnosticSet TUSet = clang_getDiagnosticSetFromTU(TU);
- PrintDiagnosticSet(TUSet);
- clang_disposeDiagnosticSet(TUSet);
- }
- void PrintMemoryUsage(CXTranslationUnit TU) {
- unsigned long total = 0;
- unsigned i = 0;
- CXTUResourceUsage usage = clang_getCXTUResourceUsage(TU);
- fprintf(stderr, "Memory usage:\n");
- for (i = 0 ; i != usage.numEntries; ++i) {
- const char *name = clang_getTUResourceUsageName(usage.entries[i].kind);
- unsigned long amount = usage.entries[i].amount;
- total += amount;
- fprintf(stderr, " %s : %ld bytes (%f MBytes)\n", name, amount,
- ((double) amount)/(1024*1024));
- }
- fprintf(stderr, " TOTAL = %ld bytes (%f MBytes)\n", total,
- ((double) total)/(1024*1024));
- clang_disposeCXTUResourceUsage(usage);
- }
- /******************************************************************************/
- /* Logic for testing traversal. */
- /******************************************************************************/
- static void PrintCursorExtent(CXCursor C) {
- CXSourceRange extent = clang_getCursorExtent(C);
- PrintRange(extent, "Extent");
- }
- /* Data used by the visitors. */
- typedef struct {
- CXTranslationUnit TU;
- enum CXCursorKind *Filter;
- const char *CommentSchemaFile;
- } VisitorData;
- enum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor,
- CXCursor Parent,
- CXClientData ClientData) {
- VisitorData *Data = (VisitorData *)ClientData;
- if (!Data->Filter || (Cursor.kind == *(enum CXCursorKind *)Data->Filter)) {
- CXSourceLocation Loc = clang_getCursorLocation(Cursor);
- unsigned line, column;
- clang_getSpellingLocation(Loc, 0, &line, &column, 0);
- printf("// %s: %s:%d:%d: ", FileCheckPrefix,
- GetCursorSource(Cursor), line, column);
- PrintCursor(Cursor, Data->CommentSchemaFile);
- PrintCursorExtent(Cursor);
- if (clang_isDeclaration(Cursor.kind)) {
- enum CX_CXXAccessSpecifier access = clang_getCXXAccessSpecifier(Cursor);
- const char *accessStr = 0;
- switch (access) {
- case CX_CXXInvalidAccessSpecifier: break;
- case CX_CXXPublic:
- accessStr = "public"; break;
- case CX_CXXProtected:
- accessStr = "protected"; break;
- case CX_CXXPrivate:
- accessStr = "private"; break;
- }
- if (accessStr)
- printf(" [access=%s]", accessStr);
- }
- printf("\n");
- return CXChildVisit_Recurse;
- }
- return CXChildVisit_Continue;
- }
- static enum CXChildVisitResult FunctionScanVisitor(CXCursor Cursor,
- CXCursor Parent,
- CXClientData ClientData) {
- const char *startBuf, *endBuf;
- unsigned startLine, startColumn, endLine, endColumn, curLine, curColumn;
- CXCursor Ref;
- VisitorData *Data = (VisitorData *)ClientData;
- if (Cursor.kind != CXCursor_FunctionDecl ||
- !clang_isCursorDefinition(Cursor))
- return CXChildVisit_Continue;
- clang_getDefinitionSpellingAndExtent(Cursor, &startBuf, &endBuf,
- &startLine, &startColumn,
- &endLine, &endColumn);
- /* Probe the entire body, looking for both decls and refs. */
- curLine = startLine;
- curColumn = startColumn;
- while (startBuf < endBuf) {
- CXSourceLocation Loc;
- CXFile file;
- CXString source;
- if (*startBuf == '\n') {
- startBuf++;
- curLine++;
- curColumn = 1;
- } else if (*startBuf != '\t')
- curColumn++;
- Loc = clang_getCursorLocation(Cursor);
- clang_getSpellingLocation(Loc, &file, 0, 0, 0);
- source = clang_getFileName(file);
- if (clang_getCString(source)) {
- CXSourceLocation RefLoc
- = clang_getLocation(Data->TU, file, curLine, curColumn);
- Ref = clang_getCursor(Data->TU, RefLoc);
- if (Ref.kind == CXCursor_NoDeclFound) {
- /* Nothing found here; that's fine. */
- } else if (Ref.kind != CXCursor_FunctionDecl) {
- printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref),
- curLine, curColumn);
- PrintCursor(Ref, Data->CommentSchemaFile);
- printf("\n");
- }
- }
- clang_disposeString(source);
- startBuf++;
- }
- return CXChildVisit_Continue;
- }
- /******************************************************************************/
- /* USR testing. */
- /******************************************************************************/
- enum CXChildVisitResult USRVisitor(CXCursor C, CXCursor parent,
- CXClientData ClientData) {
- VisitorData *Data = (VisitorData *)ClientData;
- if (!Data->Filter || (C.kind == *(enum CXCursorKind *)Data->Filter)) {
- CXString USR = clang_getCursorUSR(C);
- const char *cstr = clang_getCString(USR);
- if (!cstr || cstr[0] == '\0') {
- clang_disposeString(USR);
- return CXChildVisit_Recurse;
- }
- printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C), cstr);
- PrintCursorExtent(C);
- printf("\n");
- clang_disposeString(USR);
- return CXChildVisit_Recurse;
- }
- return CXChildVisit_Continue;
- }
- /******************************************************************************/
- /* Inclusion stack testing. */
- /******************************************************************************/
- void InclusionVisitor(CXFile includedFile, CXSourceLocation *includeStack,
- unsigned includeStackLen, CXClientData data) {
- unsigned i;
- CXString fname;
- fname = clang_getFileName(includedFile);
- printf("file: %s\nincluded by:\n", clang_getCString(fname));
- clang_disposeString(fname);
- for (i = 0; i < includeStackLen; ++i) {
- CXFile includingFile;
- unsigned line, column;
- clang_getSpellingLocation(includeStack[i], &includingFile, &line,
- &column, 0);
- fname = clang_getFileName(includingFile);
- printf(" %s:%d:%d\n", clang_getCString(fname), line, column);
- clang_disposeString(fname);
- }
- printf("\n");
- }
- void PrintInclusionStack(CXTranslationUnit TU) {
- clang_getInclusions(TU, InclusionVisitor, NULL);
- }
- /******************************************************************************/
- /* Linkage testing. */
- /******************************************************************************/
- static enum CXChildVisitResult PrintLinkage(CXCursor cursor, CXCursor p,
- CXClientData d) {
- const char *linkage = 0;
- if (clang_isInvalid(clang_getCursorKind(cursor)))
- return CXChildVisit_Recurse;
- switch (clang_getCursorLinkage(cursor)) {
- case CXLinkage_Invalid: break;
- case CXLinkage_NoLinkage: linkage = "NoLinkage"; break;
- case CXLinkage_Internal: linkage = "Internal"; break;
- case CXLinkage_UniqueExternal: linkage = "UniqueExternal"; break;
- case CXLinkage_External: linkage = "External"; break;
- }
- if (linkage) {
- PrintCursor(cursor, NULL);
- printf("linkage=%s\n", linkage);
- }
- return CXChildVisit_Recurse;
- }
- /******************************************************************************/
- /* Visibility testing. */
- /******************************************************************************/
- static enum CXChildVisitResult PrintVisibility(CXCursor cursor, CXCursor p,
- CXClientData d) {
- const char *visibility = 0;
- if (clang_isInvalid(clang_getCursorKind(cursor)))
- return CXChildVisit_Recurse;
- switch (clang_getCursorVisibility(cursor)) {
- case CXVisibility_Invalid: break;
- case CXVisibility_Hidden: visibility = "Hidden"; break;
- case CXVisibility_Protected: visibility = "Protected"; break;
- case CXVisibility_Default: visibility = "Default"; break;
- }
- if (visibility) {
- PrintCursor(cursor, NULL);
- printf("visibility=%s\n", visibility);
- }
- return CXChildVisit_Recurse;
- }
- /******************************************************************************/
- /* Typekind testing. */
- /******************************************************************************/
- static void PrintTypeAndTypeKind(CXType T, const char *Format) {
- CXString TypeSpelling, TypeKindSpelling;
- TypeSpelling = clang_getTypeSpelling(T);
- TypeKindSpelling = clang_getTypeKindSpelling(T.kind);
- printf(Format,
- clang_getCString(TypeSpelling),
- clang_getCString(TypeKindSpelling));
- clang_disposeString(TypeSpelling);
- clang_disposeString(TypeKindSpelling);
- }
- static enum CXVisitorResult FieldVisitor(CXCursor C,
- CXClientData client_data) {
- (*(int *) client_data)+=1;
- return CXVisit_Continue;
- }
- static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
- CXClientData d) {
- if (!clang_isInvalid(clang_getCursorKind(cursor))) {
- CXType T = clang_getCursorType(cursor);
- enum CXRefQualifierKind RQ = clang_Type_getCXXRefQualifier(T);
- PrintCursor(cursor, NULL);
- PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]");
- if (clang_isConstQualifiedType(T))
- printf(" const");
- if (clang_isVolatileQualifiedType(T))
- printf(" volatile");
- if (clang_isRestrictQualifiedType(T))
- printf(" restrict");
- if (RQ == CXRefQualifier_LValue)
- printf(" lvalue-ref-qualifier");
- if (RQ == CXRefQualifier_RValue)
- printf(" rvalue-ref-qualifier");
- /* Print the canonical type if it is different. */
- {
- CXType CT = clang_getCanonicalType(T);
- if (!clang_equalTypes(T, CT)) {
- PrintTypeAndTypeKind(CT, " [canonicaltype=%s] [canonicaltypekind=%s]");
- }
- }
- /* Print the return type if it exists. */
- {
- CXType RT = clang_getCursorResultType(cursor);
- if (RT.kind != CXType_Invalid) {
- PrintTypeAndTypeKind(RT, " [resulttype=%s] [resulttypekind=%s]");
- }
- }
- /* Print the argument types if they exist. */
- {
- int NumArgs = clang_Cursor_getNumArguments(cursor);
- if (NumArgs != -1 && NumArgs != 0) {
- int i;
- printf(" [args=");
- for (i = 0; i < NumArgs; ++i) {
- CXType T = clang_getCursorType(clang_Cursor_getArgument(cursor, i));
- if (T.kind != CXType_Invalid) {
- PrintTypeAndTypeKind(T, " [%s] [%s]");
- }
- }
- printf("]");
- }
- }
- /* Print the template argument types if they exist. */
- {
- int NumTArgs = clang_Type_getNumTemplateArguments(T);
- if (NumTArgs != -1 && NumTArgs != 0) {
- int i;
- printf(" [templateargs/%d=", NumTArgs);
- for (i = 0; i < NumTArgs; ++i) {
- CXType TArg = clang_Type_getTemplateArgumentAsType(T, i);
- if (TArg.kind != CXType_Invalid) {
- PrintTypeAndTypeKind(TArg, " [type=%s] [typekind=%s]");
- }
- }
- printf("]");
- }
- }
- /* Print if this is a non-POD type. */
- printf(" [isPOD=%d]", clang_isPODType(T));
- /* Print the pointee type. */
- {
- CXType PT = clang_getPointeeType(T);
- if (PT.kind != CXType_Invalid) {
- PrintTypeAndTypeKind(PT, " [pointeetype=%s] [pointeekind=%s]");
- }
- }
- /* Print the number of fields if they exist. */
- {
- int numFields = 0;
- if (clang_Type_visitFields(T, FieldVisitor, &numFields)){
- if (numFields != 0) {
- printf(" [nbFields=%d]", numFields);
- }
- /* Print if it is an anonymous record. */
- {
- unsigned isAnon = clang_Cursor_isAnonymous(cursor);
- if (isAnon != 0) {
- printf(" [isAnon=%d]", isAnon);
- }
- }
- }
- }
- printf("\n");
- }
- return CXChildVisit_Recurse;
- }
- static enum CXChildVisitResult PrintTypeSize(CXCursor cursor, CXCursor p,
- CXClientData d) {
- CXType T;
- enum CXCursorKind K = clang_getCursorKind(cursor);
- if (clang_isInvalid(K))
- return CXChildVisit_Recurse;
- T = clang_getCursorType(cursor);
- PrintCursor(cursor, NULL);
- PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]");
- /* Print the type sizeof if applicable. */
- {
- long long Size = clang_Type_getSizeOf(T);
- if (Size >= 0 || Size < -1 ) {
- printf(" [sizeof=%lld]", Size);
- }
- }
- /* Print the type alignof if applicable. */
- {
- long long Align = clang_Type_getAlignOf(T);
- if (Align >= 0 || Align < -1) {
- printf(" [alignof=%lld]", Align);
- }
- }
- /* Print the record field offset if applicable. */
- {
- CXString FieldSpelling = clang_getCursorSpelling(cursor);
- const char *FieldName = clang_getCString(FieldSpelling);
- /* recurse to get the first parent record that is not anonymous. */
- CXCursor Parent, Record;
- unsigned RecordIsAnonymous = 0;
- if (clang_getCursorKind(cursor) == CXCursor_FieldDecl) {
- Record = Parent = p;
- do {
- Record = Parent;
- Parent = clang_getCursorSemanticParent(Record);
- RecordIsAnonymous = clang_Cursor_isAnonymous(Record);
- /* Recurse as long as the parent is a CXType_Record and the Record
- is anonymous */
- } while ( clang_getCursorType(Parent).kind == CXType_Record &&
- RecordIsAnonymous > 0);
- {
- long long Offset = clang_Type_getOffsetOf(clang_getCursorType(Record),
- FieldName);
- long long Offset2 = clang_Cursor_getOffsetOfField(cursor);
- if (Offset == Offset2){
- printf(" [offsetof=%lld]", Offset);
- } else {
- /* Offsets will be different in anonymous records. */
- printf(" [offsetof=%lld/%lld]", Offset, Offset2);
- }
- }
- }
- clang_disposeString(FieldSpelling);
- }
- /* Print if its a bitfield */
- {
- int IsBitfield = clang_Cursor_isBitField(cursor);
- if (IsBitfield)
- printf(" [BitFieldSize=%d]", clang_getFieldDeclBitWidth(cursor));
- }
- printf("\n");
- return CXChildVisit_Recurse;
- }
- /******************************************************************************/
- /* Mangling testing. */
- /******************************************************************************/
- static enum CXChildVisitResult PrintMangledName(CXCursor cursor, CXCursor p,
- CXClientData d) {
- CXString MangledName;
- if (clang_isUnexposed(clang_getCursorKind(cursor)))
- return CXChildVisit_Recurse;
- PrintCursor(cursor, NULL);
- MangledName = clang_Cursor_getMangling(cursor);
- printf(" [mangled=%s]\n", clang_getCString(MangledName));
- clang_disposeString(MangledName);
- return CXChildVisit_Continue;
- }
- static enum CXChildVisitResult PrintManglings(CXCursor cursor, CXCursor p,
- CXClientData d) {
- unsigned I, E;
- CXStringSet *Manglings = NULL;
- if (clang_isUnexposed(clang_getCursorKind(cursor)))
- return CXChildVisit_Recurse;
- if (!clang_isDeclaration(clang_getCursorKind(cursor)))
- return CXChildVisit_Recurse;
- if (clang_getCursorKind(cursor) == CXCursor_ParmDecl)
- return CXChildVisit_Continue;
- PrintCursor(cursor, NULL);
- Manglings = clang_Cursor_getCXXManglings(cursor);
- for (I = 0, E = Manglings->Count; I < E; ++I)
- printf(" [mangled=%s]", clang_getCString(Manglings->Strings[I]));
- clang_disposeStringSet(Manglings);
- printf("\n");
- return CXChildVisit_Recurse;
- }
- /******************************************************************************/
- /* Bitwidth testing. */
- /******************************************************************************/
- static enum CXChildVisitResult PrintBitWidth(CXCursor cursor, CXCursor p,
- CXClientData d) {
- int Bitwidth;
- if (clang_getCursorKind(cursor) != CXCursor_FieldDecl)
- return CXChildVisit_Recurse;
- Bitwidth = clang_getFieldDeclBitWidth(cursor);
- if (Bitwidth >= 0) {
- PrintCursor(cursor, NULL);
- printf(" bitwidth=%d\n", Bitwidth);
- }
- return CXChildVisit_Recurse;
- }
- /******************************************************************************/
- /* Type declaration testing */
- /******************************************************************************/
- static enum CXChildVisitResult PrintTypeDeclaration(CXCursor cursor, CXCursor p,
- CXClientData d) {
- CXCursor typeDeclaration = clang_getTypeDeclaration(clang_getCursorType(cursor));
- if (clang_isDeclaration(typeDeclaration.kind)) {
- PrintCursor(cursor, NULL);
- PrintTypeAndTypeKind(clang_getCursorType(typeDeclaration), " [typedeclaration=%s] [typekind=%s]\n");
- }
- return CXChildVisit_Recurse;
- }
- /******************************************************************************/
- /* Loading ASTs/source. */
- /******************************************************************************/
- static int perform_test_load(CXIndex Idx, CXTranslationUnit TU,
- const char *filter, const char *prefix,
- CXCursorVisitor Visitor,
- PostVisitTU PV,
- const char *CommentSchemaFile) {
- if (prefix)
- FileCheckPrefix = prefix;
- if (Visitor) {
- enum CXCursorKind K = CXCursor_NotImplemented;
- enum CXCursorKind *ck = &K;
- VisitorData Data;
- /* Perform some simple filtering. */
- if (!strcmp(filter, "all") || !strcmp(filter, "local")) ck = NULL;
- else if (!strcmp(filter, "all-display") ||
- !strcmp(filter, "local-display")) {
- ck = NULL;
- want_display_name = 1;
- }
- else if (!strcmp(filter, "none")) K = (enum CXCursorKind) ~0;
- else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl;
- else if (!strcmp(filter, "interface")) K = CXCursor_ObjCInterfaceDecl;
- else if (!strcmp(filter, "protocol")) K = CXCursor_ObjCProtocolDecl;
- else if (!strcmp(filter, "function")) K = CXCursor_FunctionDecl;
- else if (!strcmp(filter, "typedef")) K = CXCursor_TypedefDecl;
- else if (!strcmp(filter, "scan-function")) Visitor = FunctionScanVisitor;
- else {
- fprintf(stderr, "Unknown filter for -test-load-tu: %s\n", filter);
- return 1;
- }
- Data.TU = TU;
- Data.Filter = ck;
- Data.CommentSchemaFile = CommentSchemaFile;
- clang_visitChildren(clang_getTranslationUnitCursor(TU), Visitor, &Data);
- }
- if (PV)
- PV(TU);
- PrintDiagnostics(TU);
- if (checkForErrors(TU) != 0) {
- clang_disposeTranslationUnit(TU);
- return -1;
- }
- clang_disposeTranslationUnit(TU);
- return 0;
- }
- int perform_test_load_tu(const char *file, const char *filter,
- const char *prefix, CXCursorVisitor Visitor,
- PostVisitTU PV) {
- CXIndex Idx;
- CXTranslationUnit TU;
- int result;
- Idx = clang_createIndex(/* excludeDeclsFromPCH */
- !strcmp(filter, "local") ? 1 : 0,
- /* displayDiagnostics=*/1);
- if (!CreateTranslationUnit(Idx, file, &TU)) {
- clang_disposeIndex(Idx);
- return 1;
- }
- result = perform_test_load(Idx, TU, filter, prefix, Visitor, PV, NULL);
- clang_disposeIndex(Idx);
- return result;
- }
- int perform_test_load_source(int argc, const char **argv,
- const char *filter, CXCursorVisitor Visitor,
- PostVisitTU PV) {
- CXIndex Idx;
- CXTranslationUnit TU;
- const char *CommentSchemaFile;
- struct CXUnsavedFile *unsaved_files = 0;
- int num_unsaved_files = 0;
- enum CXErrorCode Err;
- int result;
- unsigned Repeats = 0;
- unsigned I;
- Idx = clang_createIndex(/* excludeDeclsFromPCH */
- (!strcmp(filter, "local") ||
- !strcmp(filter, "local-display"))? 1 : 0,
- /* displayDiagnostics=*/1);
- if ((CommentSchemaFile = parse_comments_schema(argc, argv))) {
- argc--;
- argv++;
- }
- if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
- clang_disposeIndex(Idx);
- return -1;
- }
- if (getenv("CINDEXTEST_EDITING"))
- Repeats = 5;
- Err = clang_parseTranslationUnit2(Idx, 0,
- argv + num_unsaved_files,
- argc - num_unsaved_files,
- unsaved_files, num_unsaved_files,
- getDefaultParsingOptions(), &TU);
- if (Err != CXError_Success) {
- fprintf(stderr, "Unable to load translation unit!\n");
- describeLibclangFailure(Err);
- free_remapped_files(unsaved_files, num_unsaved_files);
- clang_disposeIndex(Idx);
- return 1;
- }
- for (I = 0; I != Repeats; ++I) {
- if (checkForErrors(TU) != 0)
- return -1;
- if (Repeats > 1) {
- Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
- clang_defaultReparseOptions(TU));
- if (Err != CXError_Success) {
- describeLibclangFailure(Err);
- free_remapped_files(unsaved_files, num_unsaved_files);
- clang_disposeIndex(Idx);
- return 1;
- }
- }
- }
- result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV,
- CommentSchemaFile);
- free_remapped_files(unsaved_files, num_unsaved_files);
- clang_disposeIndex(Idx);
- return result;
- }
- int perform_test_reparse_source(int argc, const char **argv, int trials,
- const char *filter, CXCursorVisitor Visitor,
- PostVisitTU PV) {
- CXIndex Idx;
- CXTranslationUnit TU;
- struct CXUnsavedFile *unsaved_files = 0;
- int num_unsaved_files = 0;
- int compiler_arg_idx = 0;
- enum CXErrorCode Err;
- int result, i;
- int trial;
- int remap_after_trial = 0;
- char *endptr = 0;
-
- Idx = clang_createIndex(/* excludeDeclsFromPCH */
- !strcmp(filter, "local") ? 1 : 0,
- /* displayDiagnostics=*/1);
-
- if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
- clang_disposeIndex(Idx);
- return -1;
- }
- for (i = 0; i < argc; ++i) {
- if (strcmp(argv[i], "--") == 0)
- break;
- }
- if (i < argc)
- compiler_arg_idx = i+1;
- if (num_unsaved_files > compiler_arg_idx)
- compiler_arg_idx = num_unsaved_files;
-
- /* Load the initial translation unit -- we do this without honoring remapped
- * files, so that we have a way to test results after changing the source. */
- Err = clang_parseTranslationUnit2(Idx, 0,
- argv + compiler_arg_idx,
- argc - compiler_arg_idx,
- 0, 0, getDefaultParsingOptions(), &TU);
- if (Err != CXError_Success) {
- fprintf(stderr, "Unable to load translation unit!\n");
- describeLibclangFailure(Err);
- free_remapped_files(unsaved_files, num_unsaved_files);
- clang_disposeIndex(Idx);
- return 1;
- }
-
- if (checkForErrors(TU) != 0)
- return -1;
- if (getenv("CINDEXTEST_REMAP_AFTER_TRIAL")) {
- remap_after_trial =
- strtol(getenv("CINDEXTEST_REMAP_AFTER_TRIAL"), &endptr, 10);
- }
- for (trial = 0; trial < trials; ++trial) {
- free_remapped_files(unsaved_files, num_unsaved_files);
- if (parse_remapped_files_with_try(trial, argc, argv, 0,
- &unsaved_files, &num_unsaved_files)) {
- clang_disposeTranslationUnit(TU);
- clang_disposeIndex(Idx);
- return -1;
- }
- Err = clang_reparseTranslationUnit(
- TU,
- trial >= remap_after_trial ? num_unsaved_files : 0,
- trial >= remap_after_trial ? unsaved_files : 0,
- clang_defaultReparseOptions(TU));
- if (Err != CXError_Success) {
- fprintf(stderr, "Unable to reparse translation unit!\n");
- describeLibclangFailure(Err);
- clang_disposeTranslationUnit(TU);
- free_remapped_files(unsaved_files, num_unsaved_files);
- clang_disposeIndex(Idx);
- return -1;
- }
- if (checkForErrors(TU) != 0)
- return -1;
- }
-
- result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV, NULL);
- free_remapped_files(unsaved_files, num_unsaved_files);
- clang_disposeIndex(Idx);
- return result;
- }
- /******************************************************************************/
- /* Logic for testing clang_getCursor(). */
- /******************************************************************************/
- static void print_cursor_file_scan(CXTranslationUnit TU, CXCursor cursor,
- unsigned start_line, unsigned start_col,
- unsigned end_line, unsigned end_col,
- const char *prefix) {
- printf("// %s: ", FileCheckPrefix);
- if (prefix)
- printf("-%s", prefix);
- PrintExtent(stdout, start_line, start_col, end_line, end_col);
- printf(" ");
- PrintCursor(cursor, NULL);
- printf("\n");
- }
- static int perform_file_scan(const char *ast_file, const char *source_file,
- const char *prefix) {
- CXIndex Idx;
- CXTranslationUnit TU;
- FILE *fp;
- CXCursor prevCursor = clang_getNullCursor();
- CXFile file;
- unsigned line = 1, col = 1;
- unsigned start_line = 1, start_col = 1;
- if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
- /* displayDiagnostics=*/1))) {
- fprintf(stderr, "Could not create Index\n");
- return 1;
- }
- if (!CreateTranslationUnit(Idx, ast_file, &TU))
- return 1;
- if ((fp = fopen(source_file, "r")) == NULL) {
- fprintf(stderr, "Could not open '%s'\n", source_file);
- clang_disposeTranslationUnit(TU);
- return 1;
- }
- file = clang_getFile(TU, source_file);
- for (;;) {
- CXCursor cursor;
- int c = fgetc(fp);
- if (c == '\n') {
- ++line;
- col = 1;
- } else
- ++col;
- /* Check the cursor at this position, and dump the previous one if we have
- * found something new.
- */
- cursor = clang_getCursor(TU, clang_getLocation(TU, file, line, col));
- if ((c == EOF || !clang_equalCursors(cursor, prevCursor)) &&
- prevCursor.kind != CXCursor_InvalidFile) {
- print_cursor_file_scan(TU, prevCursor, start_line, start_col,
- line, col, prefix);
- start_line = line;
- start_col = col;
- }
- if (c == EOF)
- break;
- prevCursor = cursor;
- }
- fclose(fp);
- clang_disposeTranslationUnit(TU);
- clang_disposeIndex(Idx);
- return 0;
- }
- /******************************************************************************/
- /* Logic for testing clang code completion. */
- /******************************************************************************/
- /* Parse file:line:column from the input string. Returns 0 on success, non-zero
- on failure. If successful, the pointer *filename will contain newly-allocated
- memory (that will be owned by the caller) to store the file name. */
- int parse_file_line_column(const char *input, char **filename, unsigned *line,
- unsigned *column, unsigned *second_line,
- unsigned *second_column) {
- /* Find the second colon. */
- const char *last_colon = strrchr(input, ':');
- unsigned values[4], i;
- unsigned num_values = (second_line && second_column)? 4 : 2;
- char *endptr = 0;
- if (!last_colon || last_colon == input) {
- if (num_values == 4)
- fprintf(stderr, "could not parse filename:line:column:line:column in "
- "'%s'\n", input);
- else
- fprintf(stderr, "could not parse filename:line:column in '%s'\n", input);
- return 1;
- }
- for (i = 0; i != num_values; ++i) {
- const char *prev_colon;
- /* Parse the next line or column. */
- values[num_values - i - 1] = strtol(last_colon + 1, &endptr, 10);
- if (*endptr != 0 && *endptr != ':') {
- fprintf(stderr, "could not parse %s in '%s'\n",
- (i % 2 ? "column" : "line"), input);
- return 1;
- }
- if (i + 1 == num_values)
- break;
- /* Find the previous colon. */
- prev_colon = last_colon - 1;
- while (prev_colon != input && *prev_colon != ':')
- --prev_colon;
- if (prev_colon == input) {
- fprintf(stderr, "could not parse %s in '%s'\n",
- (i % 2 == 0? "column" : "line"), input);
- return 1;
- }
- last_colon = prev_colon;
- }
- *line = values[0];
- *column = values[1];
- if (second_line && second_column) {
- *second_line = values[2];
- *second_column = values[3];
- }
- /* Copy the file name. */
- *filename = (char*)malloc(last_colon - input + 1);
- memcpy(*filename, input, last_colon - input);
- (*filename)[last_colon - input] = 0;
- return 0;
- }
- const char *
- clang_getCompletionChunkKindSpelling(enum CXCompletionChunkKind Kind) {
- switch (Kind) {
- case CXCompletionChunk_Optional: return "Optional";
- case CXCompletionChunk_TypedText: return "TypedText";
- case CXCompletionChunk_Text: return "Text";
- case CXCompletionChunk_Placeholder: return "Placeholder";
- case CXCompletionChunk_Informative: return "Informative";
- case CXCompletionChunk_CurrentParameter: return "CurrentParameter";
- case CXCompletionChunk_LeftParen: return "LeftParen";
- case CXCompletionChunk_RightParen: return "RightParen";
- case CXCompletionChunk_LeftBracket: return "LeftBracket";
- case CXCompletionChunk_RightBracket: return "RightBracket";
- case CXCompletionChunk_LeftBrace: return "LeftBrace";
- case CXCompletionChunk_RightBrace: return "RightBrace";
- case CXCompletionChunk_LeftAngle: return "LeftAngle";
- case CXCompletionChunk_RightAngle: return "RightAngle";
- case CXCompletionChunk_Comma: return "Comma";
- case CXCompletionChunk_ResultType: return "ResultType";
- case CXCompletionChunk_Colon: return "Colon";
- case CXCompletionChunk_SemiColon: return "SemiColon";
- case CXCompletionChunk_Equal: return "Equal";
- case CXCompletionChunk_HorizontalSpace: return "HorizontalSpace";
- case CXCompletionChunk_VerticalSpace: return "VerticalSpace";
- }
- return "Unknown";
- }
- static int checkForErrors(CXTranslationUnit TU) {
- unsigned Num, i;
- CXDiagnostic Diag;
- CXString DiagStr;
- if (!getenv("CINDEXTEST_FAILONERROR"))
- return 0;
- Num = clang_getNumDiagnostics(TU);
- for (i = 0; i != Num; ++i) {
- Diag = clang_getDiagnostic(TU, i);
- if (clang_getDiagnosticSeverity(Diag) >= CXDiagnostic_Error) {
- DiagStr = clang_formatDiagnostic(Diag,
- clang_defaultDiagnosticDisplayOptions());
- fprintf(stderr, "%s\n", clang_getCString(DiagStr));
- clang_disposeString(DiagStr);
- clang_disposeDiagnostic(Diag);
- return -1;
- }
- clang_disposeDiagnostic(Diag);
- }
- return 0;
- }
- static void print_completion_string(CXCompletionString completion_string,
- FILE *file) {
- int I, N;
- N = clang_getNumCompletionChunks(completion_string);
- for (I = 0; I != N; ++I) {
- CXString text;
- const char *cstr;
- enum CXCompletionChunkKind Kind
- = clang_getCompletionChunkKind(completion_string, I);
- if (Kind == CXCompletionChunk_Optional) {
- fprintf(file, "{Optional ");
- print_completion_string(
- clang_getCompletionChunkCompletionString(completion_string, I),
- file);
- fprintf(file, "}");
- continue;
- }
- if (Kind == CXCompletionChunk_VerticalSpace) {
- fprintf(file, "{VerticalSpace }");
- continue;
- }
- text = clang_getCompletionChunkText(completion_string, I);
- cstr = clang_getCString(text);
- fprintf(file, "{%s %s}",
- clang_getCompletionChunkKindSpelling(Kind),
- cstr ? cstr : "");
- clang_disposeString(text);
- }
- }
- static void print_completion_result(CXCompletionResult *completion_result,
- FILE *file) {
- CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind);
- unsigned annotationCount;
- enum CXCursorKind ParentKind;
- CXString ParentName;
- CXString BriefComment;
- const char *BriefCommentCString;
-
- fprintf(file, "%s:", clang_getCString(ks));
- clang_disposeString(ks);
- print_completion_string(completion_result->CompletionString, file);
- fprintf(file, " (%u)",
- clang_getCompletionPriority(completion_result->CompletionString));
- switch (clang_getCompletionAvailability(completion_result->CompletionString)){
- case CXAvailability_Available:
- break;
-
- case CXAvailability_Deprecated:
- fprintf(file, " (deprecated)");
- break;
-
- case CXAvailability_NotAvailable:
- fprintf(file, " (unavailable)");
- break;
- case CXAvailability_NotAccessible:
- fprintf(file, " (inaccessible)");
- break;
- }
- annotationCount = clang_getCompletionNumAnnotations(
- completion_result->CompletionString);
- if (annotationCount) {
- unsigned i;
- fprintf(file, " (");
- for (i = 0; i < annotationCount; ++i) {
- if (i != 0)
- fprintf(file, ", ");
- fprintf(file, "\"%s\"",
- clang_getCString(clang_getCompletionAnnotation(
- completion_result->CompletionString, i)));
- }
- fprintf(file, ")");
- }
- if (!getenv("CINDEXTEST_NO_COMPLETION_PARENTS")) {
- ParentName = clang_getCompletionParent(completion_result->CompletionString,
- &ParentKind);
- if (ParentKind != CXCursor_NotImplemented) {
- CXString KindSpelling = clang_getCursorKindSpelling(ParentKind);
- fprintf(file, " (parent: %s '%s')",
- clang_getCString(KindSpelling),
- clang_getCString(ParentName));
- clang_disposeString(KindSpelling);
- }
- clang_disposeString(ParentName);
- }
- BriefComment = clang_getCompletionBriefComment(
- completion_result->CompletionString);
- BriefCommentCString = clang_getCString(BriefComment);
- if (BriefCommentCString && *BriefCommentCString != '\0') {
- fprintf(file, "(brief comment: %s)", BriefCommentCString);
- }
- clang_disposeString(BriefComment);
-
- fprintf(file, "\n");
- }
- void print_completion_contexts(unsigned long long contexts, FILE *file) {
- fprintf(file, "Completion contexts:\n");
- if (contexts == CXCompletionContext_Unknown) {
- fprintf(file, "Unknown\n");
- }
- if (contexts & CXCompletionContext_AnyType) {
- fprintf(file, "Any type\n");
- }
- if (contexts & CXCompletionContext_AnyValue) {
- fprintf(file, "Any value\n");
- }
- if (contexts & CXCompletionContext_ObjCObjectValue) {
- fprintf(file, "Objective-C object value\n");
- }
- if (contexts & CXCompletionContext_ObjCSelectorValue) {
- fprintf(file, "Objective-C selector value\n");
- }
- if (contexts & CXCompletionContext_CXXClassTypeValue) {
- fprintf(file, "C++ class type value\n");
- }
- if (contexts & CXCompletionContext_DotMemberAccess) {
- fprintf(file, "Dot member access\n");
- }
- if (contexts & CXCompletionContext_ArrowMemberAccess) {
- fprintf(file, "Arrow member access\n");
- }
- if (contexts & CXCompletionContext_ObjCPropertyAccess) {
- fprintf(file, "Objective-C property access\n");
- }
- if (contexts & CXCompletionContext_EnumTag) {
- fprintf(file, "Enum tag\n");
- }
- if (contexts & CXCompletionContext_UnionTag) {
- fprintf(file, "Union tag\n");
- }
- if (contexts & CXCompletionContext_StructTag) {
- fprintf(file, "Struct tag\n");
- }
- if (contexts & CXCompletionContext_ClassTag) {
- fprintf(file, "Class name\n");
- }
- if (contexts & CXCompletionContext_Namespace) {
- fprintf(file, "Namespace or namespace alias\n");
- }
- if (contexts & CXCompletionContext_NestedNameSpecifier) {
- fprintf(file, "Nested name specifier\n");
- }
- if (contexts & CXCompletionContext_ObjCInterface) {
- fprintf(file, "Objective-C interface\n");
- }
- if (contexts & CXCompletionContext_ObjCProtocol) {
- fprintf(file, "Objective-C protocol\n");
- }
- if (contexts & CXCompletionContext_ObjCCategory) {
- fprintf(file, "Objective-C category\n");
- }
- if (contexts & CXCompletionContext_ObjCInstanceMessage) {
- fprintf(file, "Objective-C instance method\n");
- }
- if (contexts & CXCompletionContext_ObjCClassMessage) {
- fprintf(file, "Objective-C class method\n");
- }
- if (contexts & CXCompletionContext_ObjCSelectorName) {
- fprintf(file, "Objective-C selector name\n");
- }
- if (contexts & CXCompletionContext_MacroName) {
- fprintf(file, "Macro name\n");
- }
- if (contexts & CXCompletionContext_NaturalLanguage) {
- fprintf(file, "Natural language\n");
- }
- }
- int my_stricmp(const char *s1, const char *s2) {
- while (*s1 && *s2) {
- int c1 = tolower((unsigned char)*s1), c2 = tolower((unsigned char)*s2);
- if (c1 < c2)
- return -1;
- else if (c1 > c2)
- return 1;
-
- ++s1;
- ++s2;
- }
-
- if (*s1)
- return 1;
- else if (*s2)
- return -1;
- return 0;
- }
- int perform_code_completion(int argc, const char **argv, int timing_only) {
- const char *input = argv[1];
- char *filename = 0;
- unsigned line;
- unsigned column;
- CXIndex CIdx;
- int errorCode;
- struct CXUnsavedFile *unsaved_files = 0;
- int num_unsaved_files = 0;
- CXCodeCompleteResults *results = 0;
- enum CXErrorCode Err;
- CXTranslationUnit TU;
- unsigned I, Repeats = 1;
- unsigned completionOptions = clang_defaultCodeCompleteOptions();
-
- if (getenv("CINDEXTEST_CODE_COMPLETE_PATTERNS"))
- completionOptions |= CXCodeComplete_IncludeCodePatterns;
- if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS"))
- completionOptions |= CXCodeComplete_IncludeBriefComments;
-
- if (timing_only)
- input += strlen("-code-completion-timing=");
- else
- input += strlen("-code-completion-at=");
- if ((errorCode = parse_file_line_column(input, &filename, &line, &column,
- 0, 0)))
- return errorCode;
- if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files))
- return -1;
- CIdx = clang_createIndex(0, 0);
-
- if (getenv("CINDEXTEST_EDITING"))
- Repeats = 5;
- Err = clang_parseTranslationUnit2(CIdx, 0,
- argv + num_unsaved_files + 2,
- argc - num_unsaved_files - 2,
- 0, 0, getDefaultParsingOptions(), &TU);
- if (Err != CXError_Success) {
- fprintf(stderr, "Unable to load translation unit!\n");
- describeLibclangFailure(Err);
- return 1;
- }
- Err = clang_reparseTranslationUnit(TU, 0, 0,
- clang_defaultReparseOptions(TU));
- if (Err != CXError_Success) {
- fprintf(stderr, "Unable to reparse translation unit!\n");
- describeLibclangFailure(Err);
- clang_disposeTranslationUnit(TU);
- return 1;
- }
- for (I = 0; I != Repeats; ++I) {
- results = clang_codeCompleteAt(TU, filename, line, column,
- unsaved_files, num_unsaved_files,
- completionOptions);
- if (!results) {
- fprintf(stderr, "Unable to perform code completion!\n");
- return 1;
- }
- if (I != Repeats-1)
- clang_disposeCodeCompleteResults(results);
- }
- if (results) {
- unsigned i, n = results->NumResults, containerIsIncomplete = 0;
- unsigned long long contexts;
- enum CXCursorKind containerKind;
- CXString objCSelector;
- const char *selectorString;
- if (!timing_only) {
- /* Sort the code-completion results based on the typed text. */
- clang_sortCodeCompletionResults(results->Results, results->NumResults);
- for (i = 0; i != n; ++i)
- print_completion_result(results->Results + i, stdout);
- }
- n = clang_codeCompleteGetNumDiagnostics(results);
- for (i = 0; i != n; ++i) {
- CXDiagnostic diag = clang_codeCompleteGetDiagnostic(results, i);
- PrintDiagnostic(diag);
- clang_disposeDiagnostic(diag);
- }
-
- contexts = clang_codeCompleteGetContexts(results);
- print_completion_contexts(contexts, stdout);
-
- containerKind = clang_codeCompleteGetContainerKind(results,
- &containerIsIncomplete);
-
- if (containerKind != CXCursor_InvalidCode) {
- /* We have found a container */
- CXString containerUSR, containerKindSpelling;
- containerKindSpelling = clang_getCursorKindSpelling(containerKind);
- printf("Container Kind: %s\n", clang_getCString(containerKindSpelling));
- clang_disposeString(containerKindSpelling);
-
- if (containerIsIncomplete) {
- printf("Container is incomplete\n");
- }
- else {
- printf("Container is complete\n");
- }
-
- containerUSR = clang_codeCompleteGetContainerUSR(results);
- printf("Container USR: %s\n", clang_getCString(containerUSR));
- clang_disposeString(containerUSR);
- }
-
- objCSelector = clang_codeCompleteGetObjCSelector(results);
- selectorString = clang_getCString(objCSelector);
- if (selectorString && strlen(selectorString) > 0) {
- printf("Objective-C selector: %s\n", selectorString);
- }
- clang_disposeString(objCSelector);
-
- clang_disposeCodeCompleteResults(results);
- }
- clang_disposeTranslationUnit(TU);
- clang_disposeIndex(CIdx);
- free(filename);
- free_remapped_files(unsaved_files, num_unsaved_files);
- return 0;
- }
- typedef struct {
- char *filename;
- unsigned line;
- unsigned column;
- } CursorSourceLocation;
- typedef void (*cursor_handler_t)(CXCursor cursor);
- static int inspect_cursor_at(int argc, const char **argv,
- const char *locations_flag,
- cursor_handler_t handler) {
- CXIndex CIdx;
- int errorCode;
- struct CXUnsavedFile *unsaved_files = 0;
- int num_unsaved_files = 0;
- enum CXErrorCode Err;
- CXTranslationUnit TU;
- CXCursor Cursor;
- CursorSourceLocation *Locations = 0;
- unsigned NumLocations = 0, Loc;
- unsigned Repeats = 1;
- unsigned I;
-
- /* Count the number of locations. */
- while (strstr(argv[NumLocations+1], locations_flag) == argv[NumLocations+1])
- ++NumLocations;
- /* Parse the locations. */
- assert(NumLocations > 0 && "Unable to count locations?");
- Locations = (CursorSourceLocation *)malloc(
- NumLocations * sizeof(CursorSourceLocation));
- for (Loc = 0; Loc < NumLocations; ++Loc) {
- const char *input = argv[Loc + 1] + strlen(locations_flag);
- if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename,
- &Locations[Loc].line,
- &Locations[Loc].column, 0, 0)))
- return errorCode;
- }
- if (parse_remapped_files(argc, argv, NumLocations + 1, &unsaved_files,
- &num_unsaved_files))
- return -1;
- if (getenv("CINDEXTEST_EDITING"))
- Repeats = 5;
- /* Parse the translation unit. When we're testing clang_getCursor() after
- reparsing, don't remap unsaved files until the second parse. */
- CIdx = clang_createIndex(1, 1);
- Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1],
- argv + num_unsaved_files + 1 + NumLocations,
- argc - num_unsaved_files - 2 - NumLocations,
- unsaved_files,
- Repeats > 1? 0 : num_unsaved_files,
- getDefaultParsingOptions(), &TU);
- if (Err != CXError_Success) {
- fprintf(stderr, "unable to parse input\n");
- describeLibclangFailure(Err);
- return -1;
- }
- if (checkForErrors(TU) != 0)
- return -1;
- for (I = 0; I != Repeats; ++I) {
- if (Repeats > 1) {
- Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
- clang_defaultReparseOptions(TU));
- if (Err != CXError_Success) {
- describeLibclangFailure(Err);
- clang_disposeTranslationUnit(TU);
- return 1;
- }
- }
- if (checkForErrors(TU) != 0)
- return -1;
-
- for (Loc = 0; Loc < NumLocations; ++Loc) {
- CXFile file = clang_getFile(TU, Locations[Loc].filename);
- if (!file)
- continue;
- Cursor = clang_getCursor(TU,
- clang_getLocation(TU, file, Locations[Loc].line,
- Locations[Loc].column));
- if (checkForErrors(TU) != 0)
- return -1;
- if (I + 1 == Repeats) {
- handler(Cursor);
- free(Locations[Loc].filename);
- }
- }
- }
-
- PrintDiagnostics(TU);
- clang_disposeTranslationUnit(TU);
- clang_disposeIndex(CIdx);
- free(Locations);
- free_remapped_files(unsaved_files, num_unsaved_files);
- return 0;
- }
- static void inspect_print_cursor(CXCursor Cursor) {
- CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
- CXCompletionString completionString = clang_getCursorCompletionString(
- Cursor);
- CXSourceLocation CursorLoc = clang_getCursorLocation(Cursor);
- CXString Spelling;
- const char *cspell;
- unsigned line, column;
- clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0);
- printf("%d:%d ", line, column);
- PrintCursor(Cursor, NULL);
- PrintCursorExtent(Cursor);
- Spelling = clang_getCursorSpelling(Cursor);
- cspell = clang_getCString(Spelling);
- if (cspell && strlen(cspell) != 0) {
- unsigned pieceIndex;
- printf(" Spelling=%s (", cspell);
- for (pieceIndex = 0; ; ++pieceIndex) {
- CXSourceRange range =
- clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0);
- if (clang_Range_isNull(range))
- break;
- PrintRange(range, 0);
- }
- printf(")");
- }
- clang_disposeString(Spelling);
- if (clang_Cursor_getObjCSelectorIndex(Cursor) != -1)
- printf(" Selector index=%d",
- clang_Cursor_getObjCSelectorIndex(Cursor));
- if (clang_Cursor_isDynamicCall(Cursor))
- printf(" Dynamic-call");
- if (Cursor.kind == CXCursor_ObjCMessageExpr) {
- CXType T = clang_Cursor_getReceiverType(Cursor);
- CXString S = clang_getTypeKindSpelling(T.kind);
- printf(" Receiver-type=%s", clang_getCString(S));
- clang_disposeString(S);
- }
- {
- CXModule mod = clang_Cursor_getModule(Cursor);
- CXFile astFile;
- CXString name, astFilename;
- unsigned i, numHeaders;
- if (mod) {
- astFile = clang_Module_getASTFile(mod);
- astFilename = clang_getFileName(astFile);
- name = clang_Module_getFullName(mod);
- numHeaders = clang_Module_getNumTopLevelHeaders(TU, mod);
- printf(" ModuleName=%s (%s) system=%d Headers(%d):",
- clang_getCString(name), clang_getCString(astFilename),
- clang_Module_isSystem(mod), numHeaders);
- clang_disposeString(name);
- clang_disposeString(astFilename);
- for (i = 0; i < numHeaders; ++i) {
- CXFile file = clang_Module_getTopLevelHeader(TU, mod, i);
- CXString filename = clang_getFileName(file);
- printf("\n%s", clang_getCString(filename));
- clang_disposeString(filename);
- }
- }
- }
- if (completionString != NULL) {
- printf("\nCompletion string: ");
- print_completion_string(completionString, stdout);
- }
- printf("\n");
- }
- static void display_evaluate_results(CXEvalResult result) {
- switch (clang_EvalResult_getKind(result)) {
- case CXEval_Int:
- {
- int val = clang_EvalResult_getAsInt(result);
- printf("Kind: Int , Value: %d", val);
- break;
- }
- case CXEval_Float:
- {
- double val = clang_EvalResult_getAsDouble(result);
- printf("Kind: Float , Value: %f", val);
- break;
- }
- case CXEval_ObjCStrLiteral:
- {
- const char* str = clang_EvalResult_getAsStr(result);
- printf("Kind: ObjCString , Value: %s", str);
- break;
- }
- case CXEval_StrLiteral:
- {
- const char* str = clang_EvalResult_getAsStr(result);
- printf("Kind: CString , Value: %s", str);
- break;
- }
- case CXEval_CFStr:
- {
- const char* str = clang_EvalResult_getAsStr(result);
- printf("Kind: CFString , Value: %s", str);
- break;
- }
- default:
- printf("Unexposed");
- break;
- }
- }
- static void inspect_evaluate_cursor(CXCursor Cursor) {
- CXSourceLocation CursorLoc = clang_getCursorLocation(Cursor);
- CXString Spelling;
- const char *cspell;
- unsigned line, column;
- CXEvalResult ER;
- clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0);
- printf("%d:%d ", line, column);
- PrintCursor(Cursor, NULL);
- PrintCursorExtent(Cursor);
- Spelling = clang_getCursorSpelling(Cursor);
- cspell = clang_getCString(Spelling);
- if (cspell && strlen(cspell) != 0) {
- unsigned pieceIndex;
- printf(" Spelling=%s (", cspell);
- for (pieceIndex = 0; ; ++pieceIndex) {
- CXSourceRange range =
- clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0);
- if (clang_Range_isNull(range))
- break;
- PrintRange(range, 0);
- }
- printf(")");
- }
- clang_disposeString(Spelling);
- ER = clang_Cursor_Evaluate(Cursor);
- if (!ER) {
- printf("Not Evaluatable");
- } else {
- display_evaluate_results(ER);
- clang_EvalResult_dispose(ER);
- }
- printf("\n");
- }
- static void inspect_macroinfo_cursor(CXCursor Cursor) {
- CXSourceLocation CursorLoc = clang_getCursorLocation(Cursor);
- CXString Spelling;
- const char *cspell;
- unsigned line, column;
- clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0);
- printf("%d:%d ", line, column);
- PrintCursor(Cursor, NULL);
- PrintCursorExtent(Cursor);
- Spelling = clang_getCursorSpelling(Cursor);
- cspell = clang_getCString(Spelling);
- if (cspell && strlen(cspell) != 0) {
- unsigned pieceIndex;
- printf(" Spelling=%s (", cspell);
- for (pieceIndex = 0; ; ++pieceIndex) {
- CXSourceRange range =
- clang_Cursor_getSpellingNameRange(Cursor, pieceIndex, 0);
- if (clang_Range_isNull(range))
- break;
- PrintRange(range, 0);
- }
- printf(")");
- }
- clang_disposeString(Spelling);
- if (clang_Cursor_isMacroBuiltin(Cursor)) {
- printf("[builtin macro]");
- } else if (clang_Cursor_isMacroFunctionLike(Cursor)) {
- printf("[function macro]");
- }
- printf("\n");
- }
- static enum CXVisitorResult findFileRefsVisit(void *context,
- CXCursor cursor, CXSourceRange range) {
- if (clang_Range_isNull(range))
- return CXVisit_Continue;
- PrintCursor(cursor, NULL);
- PrintRange(range, "");
- printf("\n");
- return CXVisit_Continue;
- }
- static int find_file_refs_at(int argc, const char **argv) {
- CXIndex CIdx;
- int errorCode;
- struct CXUnsavedFile *unsaved_files = 0;
- int num_unsaved_files = 0;
- enum CXErrorCode Err;
- CXTranslationUnit TU;
- CXCursor Cursor;
- CursorSourceLocation *Locations = 0;
- unsigned NumLocations = 0, Loc;
- unsigned Repeats = 1;
- unsigned I;
-
- /* Count the number of locations. */
- while (strstr(argv[NumLocations+1], "-file-refs-at=") == argv[NumLocations+1])
- ++NumLocations;
- /* Parse the locations. */
- assert(NumLocations > 0 && "Unable to count locations?");
- Locations = (CursorSourceLocation *)malloc(
- NumLocations * sizeof(CursorSourceLocation));
- for (Loc = 0; Loc < NumLocations; ++Loc) {
- const char *input = argv[Loc + 1] + strlen("-file-refs-at=");
- if ((errorCode = parse_file_line_column(input, &Locations[Loc].filename,
- &Locations[Loc].line,
- &Locations[Loc].column, 0, 0)))
- return errorCode;
- }
- if (parse_remapped_files(argc, argv, NumLocations + 1, &unsaved_files,
- &num_unsaved_files))
- return -1;
- if (getenv("CINDEXTEST_EDITING"))
- Repeats = 5;
- /* Parse the translation unit. When we're testing clang_getCursor() after
- reparsing, don't remap unsaved files until the second parse. */
- CIdx = clang_createIndex(1, 1);
- Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1],
- argv + num_unsaved_files + 1 + NumLocations,
- argc - num_unsaved_files - 2 - NumLocations,
- unsaved_files,
- Repeats > 1? 0 : num_unsaved_files,
- getDefaultParsingOptions(), &TU);
- if (Err != CXError_Success) {
- fprintf(stderr, "unable to parse input\n");
- describeLibclangFailure(Err);
- clang_disposeTranslationUnit(TU);
- return -1;
- }
- if (checkForErrors(TU) != 0)
- return -1;
- for (I = 0; I != Repeats; ++I) {
- if (Repeats > 1) {
- Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
- clang_defaultReparseOptions(TU));
- if (Err != CXError_Success) {
- describeLibclangFailure(Err);
- clang_disposeTranslationUnit(TU);
- return 1;
- }
- }
- if (checkForErrors(TU) != 0)
- return -1;
-
- for (Loc = 0; Loc < NumLocations; ++Loc) {
- CXFile file = clang_getFile(TU, Locations[Loc].filename);
- if (!file)
- continue;
- Cursor = clang_getCursor(TU,
- clang_getLocation(TU, file, Locations[Loc].line,
- Locations[Loc].column));
- if (checkForErrors(TU) != 0)
- return -1;
- if (I + 1 == Repeats) {
- CXCursorAndRangeVisitor visitor = { 0, findFileRefsVisit };
- PrintCursor(Cursor, NULL);
- printf("\n");
- clang_findReferencesInFile(Cursor, file, visitor);
- free(Locations[Loc].filename);
- if (checkForErrors(TU) != 0)
- return -1;
- }
- }
- }
-
- PrintDiagnostics(TU);
- clang_disposeTranslationUnit(TU);
- clang_disposeIndex(CIdx);
- free(Locations);
- free_remapped_files(unsaved_files, num_unsaved_files);
- return 0;
- }
- static enum CXVisitorResult findFileIncludesVisit(void *context,
- CXCursor cursor, CXSourceRange range) {
- PrintCursor(cursor, NULL);
- PrintRange(range, "");
- printf("\n");
- return CXVisit_Continue;
- }
- static int find_file_includes_in(int argc, const char **argv) {
- CXIndex CIdx;
- struct CXUnsavedFile *unsaved_files = 0;
- int num_unsaved_files = 0;
- enum CXErrorCode Err;
- CXTranslationUnit TU;
- const char **Filenames = 0;
- unsigned NumFilenames = 0;
- unsigned Repeats = 1;
- unsigned I, FI;
- /* Count the number of locations. */
- while (strstr(argv[NumFilenames+1], "-file-includes-in=") == argv[NumFilenames+1])
- ++NumFilenames;
- /* Parse the locations. */
- assert(NumFilenames > 0 && "Unable to count filenames?");
- Filenames = (const char **)malloc(NumFilenames * sizeof(const char *));
- for (I = 0; I < NumFilenames; ++I) {
- const char *input = argv[I + 1] + strlen("-file-includes-in=");
- /* Copy the file name. */
- Filenames[I] = input;
- }
- if (parse_remapped_files(argc, argv, NumFilenames + 1, &unsaved_files,
- &num_unsaved_files))
- return -1;
- if (getenv("CINDEXTEST_EDITING"))
- Repeats = 2;
- /* Parse the translation unit. When we're testing clang_getCursor() after
- reparsing, don't remap unsaved files until the second parse. */
- CIdx = clang_createIndex(1, 1);
- Err = clang_parseTranslationUnit2(
- CIdx, argv[argc - 1],
- argv + num_unsaved_files + 1 + NumFilenames,
- argc - num_unsaved_files - 2 - NumFilenames,
- unsaved_files,
- Repeats > 1 ? 0 : num_unsaved_files, getDefaultParsingOptions(), &TU);
- if (Err != CXError_Success) {
- fprintf(stderr, "unable to parse input\n");
- describeLibclangFailure(Err);
- clang_disposeTranslationUnit(TU);
- return -1;
- }
- if (checkForErrors(TU) != 0)
- return -1;
- for (I = 0; I != Repeats; ++I) {
- if (Repeats > 1) {
- Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
- clang_defaultReparseOptions(TU));
- if (Err != CXError_Success) {
- describeLibclangFailure(Err);
- clang_disposeTranslationUnit(TU);
- return 1;
- }
- }
- if (checkForErrors(TU) != 0)
- return -1;
- for (FI = 0; FI < NumFilenames; ++FI) {
- CXFile file = clang_getFile(TU, Filenames[FI]);
- if (!file)
- continue;
- if (checkForErrors(TU) != 0)
- return -1;
- if (I + 1 == Repeats) {
- CXCursorAndRangeVisitor visitor = { 0, findFileIncludesVisit };
- clang_findIncludesInFile(TU, file, visitor);
- if (checkForErrors(TU) != 0)
- return -1;
- }
- }
- }
- PrintDiagnostics(TU);
- clang_disposeTranslationUnit(TU);
- clang_disposeIndex(CIdx);
- free((void *)Filenames);
- free_remapped_files(unsaved_files, num_unsaved_files);
- return 0;
- }
- #define MAX_IMPORTED_ASTFILES 200
- typedef struct {
- char **filenames;
- unsigned num_files;
- } ImportedASTFilesData;
- static ImportedASTFilesData *importedASTs_create() {
- ImportedASTFilesData *p;
- p = malloc(sizeof(ImportedASTFilesData));
- p->filenames = malloc(MAX_IMPORTED_ASTFILES * sizeof(const char *));
- p->num_files = 0;
- return p;
- }
- static void importedASTs_dispose(ImportedASTFilesData *p) {
- unsigned i;
- if (!p)
- return;
- for (i = 0; i < p->num_files; ++i)
- free(p->filenames[i]);
- free(p->filenames);
- free(p);
- }
- static void importedASTS_insert(ImportedASTFilesData *p, const char *file) {
- unsigned i;
- assert(p && file);
- for (i = 0; i < p->num_files; ++i)
- if (strcmp(file, p->filenames[i]) == 0)
- return;
- assert(p->num_files + 1 < MAX_IMPORTED_ASTFILES);
- p->filenames[p->num_files++] = strdup(file);
- }
- typedef struct IndexDataStringList_ {
- struct IndexDataStringList_ *next;
- char data[1]; /* Dynamically sized. */
- } IndexDataStringList;
- typedef struct {
- const char *check_prefix;
- int first_check_printed;
- int fail_for_error;
- int abort;
- const char *main_filename;
- ImportedASTFilesData *importedASTs;
- IndexDataStringList *strings;
- CXTranslationUnit TU;
- } IndexData;
- static void free_client_data(IndexData *index_data) {
- IndexDataStringList *node = index_data->strings;
- while (node) {
- IndexDataStringList *next = node->next;
- free(node);
- node = next;
- }
- index_data->strings = NULL;
- }
- static void printCheck(IndexData *data) {
- if (data->check_prefix) {
- if (data->first_check_printed) {
- printf("// %s-NEXT: ", data->check_prefix);
- } else {
- printf("// %s : ", data->check_prefix);
- data->first_check_printed = 1;
- }
- }
- }
- static void printCXIndexFile(CXIdxClientFile file) {
- CXString filename = clang_getFileName((CXFile)file);
- printf("%s", clang_getCString(filename));
- clang_disposeString(filename);
- }
- static void printCXIndexLoc(CXIdxLoc loc, CXClientData client_data) {
- IndexData *index_data;
- CXString filename;
- const char *cname;
- CXIdxClientFile file;
- unsigned line, column;
- int isMainFile;
-
- index_data = (IndexData *)client_data;
- clang_indexLoc_getFileLocation(loc, &file, 0, &line, &column, 0);
- if (line == 0) {
- printf("<invalid>");
- return;
- }
- if (!file) {
- printf("<no idxfile>");
- return;
- }
- filename = clang_getFileName((CXFile)file);
- cname = clang_getCString(filename);
- if (strcmp(cname, index_data->main_filename) == 0)
- isMainFile = 1;
- else
- isMainFile = 0;
- clang_disposeString(filename);
- if (!isMainFile) {
- printCXIndexFile(file);
- printf(":");
- }
- printf("%d:%d", line, column);
- }
- static unsigned digitCount(unsigned val) {
- unsigned c = 1;
- while (1) {
- if (val < 10)
- return c;
- ++c;
- val /= 10;
- }
- }
- static CXIdxClientContainer makeClientContainer(CXClientData *client_data,
- const CXIdxEntityInfo *info,
- CXIdxLoc loc) {
- IndexData *index_data;
- IndexDataStringList *node;
- const char *name;
- char *newStr;
- CXIdxClientFile file;
- unsigned line, column;
-
- name = info->name;
- if (!name)
- name = "<anon-tag>";
- clang_indexLoc_getFileLocation(loc, &file, 0, &line, &column, 0);
- node =
- (IndexDataStringList *)malloc(sizeof(IndexDataStringList) + strlen(name) +
- digitCount(line) + digitCount(column) + 2);
- newStr = node->data;
- sprintf(newStr, "%s:%d:%d", name, line, column);
- /* Remember string so it can be freed later. */
- index_data = (IndexData *)client_data;
- node->next = index_data->strings;
- index_data->strings = node;
- return (CXIdxClientContainer)newStr;
- }
- static void printCXIndexContainer(const CXIdxContainerInfo *info) {
- CXIdxClientContainer container;
- container = clang_index_getClientContainer(info);
- if (!container)
- printf("[<<NULL>>]");
- else
- printf("[%s]", (const char *)container);
- }
- static const char *getEntityKindString(CXIdxEntityKind kind) {
- switch (kind) {
- case CXIdxEntity_Unexposed: return "<<UNEXPOSED>>";
- case CXIdxEntity_Typedef: return "typedef";
- case CXIdxEntity_Function: return "function";
- case CXIdxEntity_Variable: return "variable";
- case CXIdxEntity_Field: return "field";
- case CXIdxEntity_EnumConstant: return "enumerator";
- case CXIdxEntity_ObjCClass: return "objc-class";
- case CXIdxEntity_ObjCProtocol: return "objc-protocol";
- case CXIdxEntity_ObjCCategory: return "objc-category";
- case CXIdxEntity_ObjCInstanceMethod: return "objc-instance-method";
- case CXIdxEntity_ObjCClassMethod: return "objc-class-method";
- case CXIdxEntity_ObjCProperty: return "objc-property";
- case CXIdxEntity_ObjCIvar: return "objc-ivar";
- case CXIdxEntity_Enum: return "enum";
- case CXIdxEntity_Struct: return "struct";
- case CXIdxEntity_Union: return "union";
- case CXIdxEntity_CXXClass: return "c++-class";
- case CXIdxEntity_CXXNamespace: return "namespace";
- case CXIdxEntity_CXXNamespaceAlias: return "namespace-alias";
- case CXIdxEntity_CXXStaticVariable: return "c++-static-var";
- case CXIdxEntity_CXXStaticMethod: return "c++-static-method";
- case CXIdxEntity_CXXInstanceMethod: return "c++-instance-method";
- case CXIdxEntity_CXXConstructor: return "constructor";
- case CXIdxEntity_CXXDestructor: return "destructor";
- case CXIdxEntity_CXXConversionFunction: return "conversion-func";
- case CXIdxEntity_CXXTypeAlias: return "type-alias";
- case CXIdxEntity_CXXInterface: return "c++-__interface";
- }
- assert(0 && "Garbage entity kind");
- return 0;
- }
- static const char *getEntityTemplateKindString(CXIdxEntityCXXTemplateKind kind) {
- switch (kind) {
- case CXIdxEntity_NonTemplate: return "";
- case CXIdxEntity_Template: return "-template";
- case CXIdxEntity_TemplatePartialSpecialization:
- return "-template-partial-spec";
- case CXIdxEntity_TemplateSpecialization: return "-template-spec";
- }
- assert(0 && "Garbage entity kind");
- return 0;
- }
- static const char *getEntityLanguageString(CXIdxEntityLanguage kind) {
- switch (kind) {
- case CXIdxEntityLang_None: return "<none>";
- case CXIdxEntityLang_C: return "C";
- case CXIdxEntityLang_ObjC: return "ObjC";
- case CXIdxEntityLang_CXX: return "C++";
- }
- assert(0 && "Garbage language kind");
- return 0;
- }
- static void printEntityInfo(const char *cb,
- CXClientData client_data,
- const CXIdxEntityInfo *info) {
- const char *name;
- IndexData *index_data;
- unsigned i;
- index_data = (IndexData *)client_data;
- printCheck(index_data);
- if (!info) {
- printf("%s: <<NULL>>", cb);
- return;
- }
- name = info->name;
- if (!name)
- name = "<anon-tag>";
- printf("%s: kind: %s%s", cb, getEntityKindString(info->kind),
- getEntityTemplateKindString(info->templateKind));
- printf(" | name: %s", name);
- printf(" | USR: %s", info->USR);
- printf(" | lang: %s", getEntityLanguageString(info->lang));
- for (i = 0; i != info->numAttributes; ++i) {
- const CXIdxAttrInfo *Attr = info->attributes[i];
- printf(" <attribute>: ");
- PrintCursor(Attr->cursor, NULL);
- }
- }
- static void printBaseClassInfo(CXClientData client_data,
- const CXIdxBaseClassInfo *info) {
- printEntityInfo(" <base>", client_data, info->base);
- printf(" | cursor: ");
- PrintCursor(info->cursor, NULL);
- printf(" | loc: ");
- printCXIndexLoc(info->loc, client_data);
- }
- static void printProtocolList(const CXIdxObjCProtocolRefListInfo *ProtoInfo,
- CXClientData client_data) {
- unsigned i;
- for (i = 0; i < ProtoInfo->numProtocols; ++i) {
- printEntityInfo(" <protocol>", client_data,
- ProtoInfo->protocols[i]->protocol);
- printf(" | cursor: ");
- PrintCursor(ProtoInfo->protocols[i]->cursor, NULL);
- printf(" | loc: ");
- printCXIndexLoc(ProtoInfo->protocols[i]->loc, client_data);
- printf("\n");
- }
- }
- static void index_diagnostic(CXClientData client_data,
- CXDiagnosticSet diagSet, void *reserved) {
- CXString str;
- const char *cstr;
- unsigned numDiags, i;
- CXDiagnostic diag;
- IndexData *index_data;
- index_data = (IndexData *)client_data;
- printCheck(index_data);
- numDiags = clang_getNumDiagnosticsInSet(diagSet);
- for (i = 0; i != numDiags; ++i) {
- diag = clang_getDiagnosticInSet(diagSet, i);
- str = clang_formatDiagnostic(diag, clang_defaultDiagnosticDisplayOptions());
- cstr = clang_getCString(str);
- printf("[diagnostic]: %s\n", cstr);
- clang_disposeString(str);
-
- if (getenv("CINDEXTEST_FAILONERROR") &&
- clang_getDiagnosticSeverity(diag) >= CXDiagnostic_Error) {
- index_data->fail_for_error = 1;
- }
- }
- }
- static CXIdxClientFile index_enteredMainFile(CXClientData client_data,
- CXFile file, void *reserved) {
- IndexData *index_data;
- CXString filename;
- index_data = (IndexData *)client_data;
- printCheck(index_data);
- filename = clang_getFileName(file);
- index_data->main_filename = clang_getCString(filename);
- clang_disposeString(filename);
- printf("[enteredMainFile]: ");
- printCXIndexFile((CXIdxClientFile)file);
- printf("\n");
- return (CXIdxClientFile)file;
- }
- static CXIdxClientFile index_ppIncludedFile(CXClientData client_data,
- const CXIdxIncludedFileInfo *info) {
- IndexData *index_data;
- CXModule Mod;
- index_data = (IndexData *)client_data;
- printCheck(index_data);
- printf("[ppIncludedFile]: ");
- printCXIndexFile((CXIdxClientFile)info->file);
- printf(" | name: \"%s\"", info->filename);
- printf(" | hash loc: ");
- printCXIndexLoc(info->hashLoc, client_data);
- printf(" | isImport: %d | isAngled: %d | isModule: %d",
- info->isImport, info->isAngled, info->isModuleImport);
-
- Mod = clang_getModuleForFile(index_data->TU, (CXFile)info->file);
- if (Mod) {
- CXString str = clang_Module_getFullName(Mod);
- const char *cstr = clang_getCString(str);
- printf(" | module: %s", cstr);
- clang_disposeString(str);
- }
- printf("\n");
- return (CXIdxClientFile)info->file;
- }
- static CXIdxClientFile index_importedASTFile(CXClientData client_data,
- const CXIdxImportedASTFileInfo *info) {
- IndexData *index_data;
- index_data = (IndexData *)client_data;
- printCheck(index_data);
- if (index_data->importedASTs) {
- CXString filename = clang_getFileName(info->file);
- importedASTS_insert(index_data->importedASTs, clang_getCString(filename));
- clang_disposeString(filename);
- }
-
- printf("[importedASTFile]: ");
- printCXIndexFile((CXIdxClientFile)info->file);
- if (info->module) {
- CXString name = clang_Module_getFullName(info->module);
- printf(" | loc: ");
- printCXIndexLoc(info->loc, client_data);
- printf(" | name: \"%s\"", clang_getCString(name));
- printf(" | isImplicit: %d\n", info->isImplicit);
- clang_disposeString(name);
- } else {
- /* PCH file, the rest are not relevant. */
- printf("\n");
- }
- return (CXIdxClientFile)info->file;
- }
- static CXIdxClientContainer
- index_startedTranslationUnit(CXClientData client_data, void *reserved) {
- IndexData *index_data;
- index_data = (IndexData *)client_data;
- printCheck(index_data);
- printf("[startedTranslationUnit]\n");
- return (CXIdxClientContainer)"TU";
- }
- static void index_indexDeclaration(CXClientData client_data,
- const CXIdxDeclInfo *info) {
- IndexData *index_data;
- const CXIdxObjCCategoryDeclInfo *CatInfo;
- const CXIdxObjCInterfaceDeclInfo *InterInfo;
- const CXIdxObjCProtocolRefListInfo *ProtoInfo;
- const CXIdxObjCPropertyDeclInfo *PropInfo;
- const CXIdxCXXClassDeclInfo *CXXClassInfo;
- unsigned i;
- index_data = (IndexData *)client_data;
- printEntityInfo("[indexDeclaration]", client_data, info->entityInfo);
- printf(" | cursor: ");
- PrintCursor(info->cursor, NULL);
- printf(" | loc: ");
- printCXIndexLoc(info->loc, client_data);
- printf(" | semantic-container: ");
- printCXIndexContainer(info->semanticContainer);
- printf(" | lexical-container: ");
- printCXIndexContainer(info->lexicalContainer);
- printf(" | isRedecl: %d", info->isRedeclaration);
- printf(" | isDef: %d", info->isDefinition);
- if (info->flags & CXIdxDeclFlag_Skipped) {
- assert(!info->isContainer);
- printf(" | isContainer: skipped");
- } else {
- printf(" | isContainer: %d", info->isContainer);
- }
- printf(" | isImplicit: %d\n", info->isImplicit);
- for (i = 0; i != info->numAttributes; ++i) {
- const CXIdxAttrInfo *Attr = info->attributes[i];
- printf(" <attribute>: ");
- PrintCursor(Attr->cursor, NULL);
- printf("\n");
- }
- if (clang_index_isEntityObjCContainerKind(info->entityInfo->kind)) {
- const char *kindName = 0;
- CXIdxObjCContainerKind K = clang_index_getObjCContainerDeclInfo(info)->kind;
- switch (K) {
- case CXIdxObjCContainer_ForwardRef:
- kindName = "forward-ref"; break;
- case CXIdxObjCContainer_Interface:
- kindName = "interface"; break;
- case CXIdxObjCContainer_Implementation:
- kindName = "implementation"; break;
- }
- printCheck(index_data);
- printf(" <ObjCContainerInfo>: kind: %s\n", kindName);
- }
- if ((CatInfo = clang_index_getObjCCategoryDeclInfo(info))) {
- printEntityInfo(" <ObjCCategoryInfo>: class", client_data,
- CatInfo->objcClass);
- printf(" | cursor: ");
- PrintCursor(CatInfo->classCursor, NULL);
- printf(" | loc: ");
- printCXIndexLoc(CatInfo->classLoc, client_data);
- printf("\n");
- }
- if ((InterInfo = clang_index_getObjCInterfaceDeclInfo(info))) {
- if (InterInfo->superInfo) {
- printBaseClassInfo(client_data, InterInfo->superInfo);
- printf("\n");
- }
- }
- if ((ProtoInfo = clang_index_getObjCProtocolRefListInfo(info))) {
- printProtocolList(ProtoInfo, client_data);
- }
- if ((PropInfo = clang_index_getObjCPropertyDeclInfo(info))) {
- if (PropInfo->getter) {
- printEntityInfo(" <getter>", client_data, PropInfo->getter);
- printf("\n");
- }
- if (PropInfo->setter) {
- printEntityInfo(" <setter>", client_data, PropInfo->setter);
- printf("\n");
- }
- }
- if ((CXXClassInfo = clang_index_getCXXClassDeclInfo(info))) {
- for (i = 0; i != CXXClassInfo->numBases; ++i) {
- printBaseClassInfo(client_data, CXXClassInfo->bases[i]);
- printf("\n");
- }
- }
- if (info->declAsContainer)
- clang_index_setClientContainer(
- info->declAsContainer,
- makeClientContainer(client_data, info->entityInfo, info->loc));
- }
- static void index_indexEntityReference(CXClientData client_data,
- const CXIdxEntityRefInfo *info) {
- printEntityInfo("[indexEntityReference]", client_data,
- info->referencedEntity);
- printf(" | cursor: ");
- PrintCursor(info->cursor, NULL);
- printf(" | loc: ");
- printCXIndexLoc(info->loc, client_data);
- printEntityInfo(" | <parent>:", client_data, info->parentEntity);
- printf(" | container: ");
- printCXIndexContainer(info->container);
- printf(" | refkind: ");
- switch (info->kind) {
- case CXIdxEntityRef_Direct: printf("direct"); break;
- case CXIdxEntityRef_Implicit: printf("implicit"); break;
- }
- printf("\n");
- }
- static int index_abortQuery(CXClientData client_data, void *reserved) {
- IndexData *index_data;
- index_data = (IndexData *)client_data;
- return index_data->abort;
- }
- static IndexerCallbacks IndexCB = {
- index_abortQuery,
- index_diagnostic,
- index_enteredMainFile,
- index_ppIncludedFile,
- index_importedASTFile,
- index_startedTranslationUnit,
- index_indexDeclaration,
- index_indexEntityReference
- };
- static unsigned getIndexOptions(void) {
- unsigned index_opts;
- index_opts = 0;
- if (getenv("CINDEXTEST_SUPPRESSREFS"))
- index_opts |= CXIndexOpt_SuppressRedundantRefs;
- if (getenv("CINDEXTEST_INDEXLOCALSYMBOLS"))
- index_opts |= CXIndexOpt_IndexFunctionLocalSymbols;
- if (!getenv("CINDEXTEST_DISABLE_SKIPPARSEDBODIES"))
- index_opts |= CXIndexOpt_SkipParsedBodiesInSession;
- return index_opts;
- }
- static int index_compile_args(int num_args, const char **args,
- CXIndexAction idxAction,
- ImportedASTFilesData *importedASTs,
- const char *check_prefix) {
- IndexData index_data;
- unsigned index_opts;
- int result;
- if (num_args == 0) {
- fprintf(stderr, "no compiler arguments\n");
- return -1;
- }
- index_data.check_prefix = check_prefix;
- index_data.first_check_printed = 0;
- index_data.fail_for_error = 0;
- index_data.abort = 0;
- index_data.main_filename = "";
- index_data.importedASTs = importedASTs;
- index_data.strings = NULL;
- index_data.TU = NULL;
- index_opts = getIndexOptions();
- result = clang_indexSourceFile(idxAction, &index_data,
- &IndexCB,sizeof(IndexCB), index_opts,
- 0, args, num_args, 0, 0, 0,
- getDefaultParsingOptions());
- if (result != CXError_Success)
- describeLibclangFailure(result);
- if (index_data.fail_for_error)
- result = -1;
- free_client_data(&index_data);
- return result;
- }
- static int index_ast_file(const char *ast_file,
- CXIndex Idx,
- CXIndexAction idxAction,
- ImportedASTFilesData *importedASTs,
- const char *check_prefix) {
- CXTranslationUnit TU;
- IndexData index_data;
- unsigned index_opts;
- int result;
- if (!CreateTranslationUnit(Idx, ast_file, &TU))
- return -1;
- index_data.check_prefix = check_prefix;
- index_data.first_check_printed = 0;
- index_data.fail_for_error = 0;
- index_data.abort = 0;
- index_data.main_filename = "";
- index_data.importedASTs = importedASTs;
- index_data.strings = NULL;
- index_data.TU = TU;
- index_opts = getIndexOptions();
- result = clang_indexTranslationUnit(idxAction, &index_data,
- &IndexCB,sizeof(IndexCB),
- index_opts, TU);
- if (index_data.fail_for_error)
- result = -1;
- clang_disposeTranslationUnit(TU);
- free_client_data(&index_data);
- return result;
- }
- static int index_file(int argc, const char **argv, int full) {
- const char *check_prefix;
- CXIndex Idx;
- CXIndexAction idxAction;
- ImportedASTFilesData *importedASTs;
- int result;
- check_prefix = 0;
- if (argc > 0) {
- if (strstr(argv[0], "-check-prefix=") == argv[0]) {
- check_prefix = argv[0] + strlen("-check-prefix=");
- ++argv;
- --argc;
- }
- }
- if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
- /* displayDiagnostics=*/1))) {
- fprintf(stderr, "Could not create Index\n");
- return 1;
- }
- idxAction = clang_IndexAction_create(Idx);
- importedASTs = 0;
- if (full)
- importedASTs = importedASTs_create();
- result = index_compile_args(argc, argv, idxAction, importedASTs, check_prefix);
- if (result != 0)
- goto finished;
- if (full) {
- unsigned i;
- for (i = 0; i < importedASTs->num_files && result == 0; ++i) {
- result = index_ast_file(importedASTs->filenames[i], Idx, idxAction,
- importedASTs, check_prefix);
- }
- }
- finished:
- importedASTs_dispose(importedASTs);
- clang_IndexAction_dispose(idxAction);
- clang_disposeIndex(Idx);
- return result;
- }
- static int index_tu(int argc, const char **argv) {
- const char *check_prefix;
- CXIndex Idx;
- CXIndexAction idxAction;
- int result;
- check_prefix = 0;
- if (argc > 0) {
- if (strstr(argv[0], "-check-prefix=") == argv[0]) {
- check_prefix = argv[0] + strlen("-check-prefix=");
- ++argv;
- --argc;
- }
- }
- if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
- /* displayDiagnostics=*/1))) {
- fprintf(stderr, "Could not create Index\n");
- return 1;
- }
- idxAction = clang_IndexAction_create(Idx);
- result = index_ast_file(argv[0], Idx, idxAction,
- /*importedASTs=*/0, check_prefix);
- clang_IndexAction_dispose(idxAction);
- clang_disposeIndex(Idx);
- return result;
- }
- static int index_compile_db(int argc, const char **argv) {
- const char *check_prefix;
- CXIndex Idx;
- CXIndexAction idxAction;
- int errorCode = 0;
- check_prefix = 0;
- if (argc > 0) {
- if (strstr(argv[0], "-check-prefix=") == argv[0]) {
- check_prefix = argv[0] + strlen("-check-prefix=");
- ++argv;
- --argc;
- }
- }
- if (argc == 0) {
- fprintf(stderr, "no compilation database\n");
- return -1;
- }
- if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
- /* displayDiagnostics=*/1))) {
- fprintf(stderr, "Could not create Index\n");
- return 1;
- }
- idxAction = clang_IndexAction_create(Idx);
- {
- const char *database = argv[0];
- CXCompilationDatabase db = 0;
- CXCompileCommands CCmds = 0;
- CXCompileCommand CCmd;
- CXCompilationDatabase_Error ec;
- CXString wd;
- #define MAX_COMPILE_ARGS 512
- CXString cxargs[MAX_COMPILE_ARGS];
- const char *args[MAX_COMPILE_ARGS];
- char *tmp;
- unsigned len;
- char *buildDir;
- int i, a, numCmds, numArgs;
- len = strlen(database);
- tmp = (char *) malloc(len+1);
- memcpy(tmp, database, len+1);
- buildDir = dirname(tmp);
- db = clang_CompilationDatabase_fromDirectory(buildDir, &ec);
- if (db) {
- if (ec!=CXCompilationDatabase_NoError) {
- printf("unexpected error %d code while loading compilation database\n", ec);
- errorCode = -1;
- goto cdb_end;
- }
- if (chdir(buildDir) != 0) {
- printf("Could not chdir to %s\n", buildDir);
- errorCode = -1;
- goto cdb_end;
- }
- CCmds = clang_CompilationDatabase_getAllCompileCommands(db);
- if (!CCmds) {
- printf("compilation db is empty\n");
- errorCode = -1;
- goto cdb_end;
- }
- numCmds = clang_CompileCommands_getSize(CCmds);
- if (numCmds==0) {
- fprintf(stderr, "should not get an empty compileCommand set\n");
- errorCode = -1;
- goto cdb_end;
- }
- for (i=0; i<numCmds && errorCode == 0; ++i) {
- CCmd = clang_CompileCommands_getCommand(CCmds, i);
- wd = clang_CompileCommand_getDirectory(CCmd);
- if (chdir(clang_getCString(wd)) != 0) {
- printf("Could not chdir to %s\n", clang_getCString(wd));
- errorCode = -1;
- goto cdb_end;
- }
- clang_disposeString(wd);
- numArgs = clang_CompileCommand_getNumArgs(CCmd);
- if (numArgs > MAX_COMPILE_ARGS){
- fprintf(stderr, "got more compile arguments than maximum\n");
- errorCode = -1;
- goto cdb_end;
- }
- for (a=0; a<numArgs; ++a) {
- cxargs[a] = clang_CompileCommand_getArg(CCmd, a);
- args[a] = clang_getCString(cxargs[a]);
- }
- errorCode = index_compile_args(numArgs, args, idxAction,
- /*importedASTs=*/0, check_prefix);
- for (a=0; a<numArgs; ++a)
- clang_disposeString(cxargs[a]);
- }
- } else {
- printf("database loading failed with error code %d.\n", ec);
- errorCode = -1;
- }
- cdb_end:
- clang_CompileCommands_dispose(CCmds);
- clang_CompilationDatabase_dispose(db);
- free(tmp);
- }
- clang_IndexAction_dispose(idxAction);
- clang_disposeIndex(Idx);
- return errorCode;
- }
- int perform_token_annotation(int argc, const char **argv) {
- const char *input = argv[1];
- char *filename = 0;
- unsigned line, second_line;
- unsigned column, second_column;
- CXIndex CIdx;
- CXTranslationUnit TU = 0;
- int errorCode;
- struct CXUnsavedFile *unsaved_files = 0;
- int num_unsaved_files = 0;
- CXToken *tokens;
- unsigned num_tokens;
- CXSourceRange range;
- CXSourceLocation startLoc, endLoc;
- CXFile file = 0;
- CXCursor *cursors = 0;
- CXSourceRangeList *skipped_ranges = 0;
- enum CXErrorCode Err;
- unsigned i;
- input += strlen("-test-annotate-tokens=");
- if ((errorCode = parse_file_line_column(input, &filename, &line, &column,
- &second_line, &second_column)))
- return errorCode;
- if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files)) {
- free(filename);
- return -1;
- }
- CIdx = clang_createIndex(0, 1);
- Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1],
- argv + num_unsaved_files + 2,
- argc - num_unsaved_files - 3,
- unsaved_files,
- num_unsaved_files,
- getDefaultParsingOptions(), &TU);
- if (Err != CXError_Success) {
- fprintf(stderr, "unable to parse input\n");
- describeLibclangFailure(Err);
- clang_disposeIndex(CIdx);
- free(filename);
- free_remapped_files(unsaved_files, num_unsaved_files);
- return -1;
- }
- errorCode = 0;
- if (checkForErrors(TU) != 0) {
- errorCode = -1;
- goto teardown;
- }
- if (getenv("CINDEXTEST_EDITING")) {
- for (i = 0; i < 5; ++i) {
- Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
- clang_defaultReparseOptions(TU));
- if (Err != CXError_Success) {
- fprintf(stderr, "Unable to reparse translation unit!\n");
- describeLibclangFailure(Err);
- errorCode = -1;
- goto teardown;
- }
- }
- }
- if (checkForErrors(TU) != 0) {
- errorCode = -1;
- goto teardown;
- }
- file = clang_getFile(TU, filename);
- if (!file) {
- fprintf(stderr, "file %s is not in this translation unit\n", filename);
- errorCode = -1;
- goto teardown;
- }
- startLoc = clang_getLocation(TU, file, line, column);
- if (clang_equalLocations(clang_getNullLocation(), startLoc)) {
- fprintf(stderr, "invalid source location %s:%d:%d\n", filename, line,
- column);
- errorCode = -1;
- goto teardown;
- }
- endLoc = clang_getLocation(TU, file, second_line, second_column);
- if (clang_equalLocations(clang_getNullLocation(), endLoc)) {
- fprintf(stderr, "invalid source location %s:%d:%d\n", filename,
- second_line, second_column);
- errorCode = -1;
- goto teardown;
- }
- range = clang_getRange(startLoc, endLoc);
- clang_tokenize(TU, range, &tokens, &num_tokens);
- if (checkForErrors(TU) != 0) {
- errorCode = -1;
- goto teardown;
- }
- cursors = (CXCursor *)malloc(num_tokens * sizeof(CXCursor));
- clang_annotateTokens(TU, tokens, num_tokens, cursors);
- if (checkForErrors(TU) != 0) {
- errorCode = -1;
- goto teardown;
- }
- skipped_ranges = clang_getSkippedRanges(TU, file);
- for (i = 0; i != skipped_ranges->count; ++i) {
- unsigned start_line, start_column, end_line, end_column;
- clang_getSpellingLocation(clang_getRangeStart(skipped_ranges->ranges[i]),
- 0, &start_line, &start_column, 0);
- clang_getSpellingLocation(clang_getRangeEnd(skipped_ranges->ranges[i]),
- 0, &end_line, &end_column, 0);
- printf("Skipping: ");
- PrintExtent(stdout, start_line, start_column, end_line, end_column);
- printf("\n");
- }
- clang_disposeSourceRangeList(skipped_ranges);
- for (i = 0; i != num_tokens; ++i) {
- const char *kind = "<unknown>";
- CXString spelling = clang_getTokenSpelling(TU, tokens[i]);
- CXSourceRange extent = clang_getTokenExtent(TU, tokens[i]);
- unsigned start_line, start_column, end_line, end_column;
- switch (clang_getTokenKind(tokens[i])) {
- case CXToken_Punctuation: kind = "Punctuation"; break;
- case CXToken_Keyword: kind = "Keyword"; break;
- case CXToken_Identifier: kind = "Identifier"; break;
- case CXToken_Literal: kind = "Literal"; break;
- case CXToken_Comment: kind = "Comment"; break;
- }
- clang_getSpellingLocation(clang_getRangeStart(extent),
- 0, &start_line, &start_column, 0);
- clang_getSpellingLocation(clang_getRangeEnd(extent),
- 0, &end_line, &end_column, 0);
- printf("%s: \"%s\" ", kind, clang_getCString(spelling));
- clang_disposeString(spelling);
- PrintExtent(stdout, start_line, start_column, end_line, end_column);
- if (!clang_isInvalid(cursors[i].kind)) {
- printf(" ");
- PrintCursor(cursors[i], NULL);
- }
- printf("\n");
- }
- free(cursors);
- clang_disposeTokens(TU, tokens, num_tokens);
- teardown:
- PrintDiagnostics(TU);
- clang_disposeTranslationUnit(TU);
- clang_disposeIndex(CIdx);
- free(filename);
- free_remapped_files(unsaved_files, num_unsaved_files);
- return errorCode;
- }
- static int
- perform_test_compilation_db(const char *database, int argc, const char **argv) {
- CXCompilationDatabase db;
- CXCompileCommands CCmds;
- CXCompileCommand CCmd;
- CXCompilationDatabase_Error ec;
- CXString wd;
- CXString arg;
- int errorCode = 0;
- char *tmp;
- unsigned len;
- char *buildDir;
- int i, j, a, numCmds, numArgs;
- len = strlen(database);
- tmp = (char *) malloc(len+1);
- memcpy(tmp, database, len+1);
- buildDir = dirname(tmp);
- db = clang_CompilationDatabase_fromDirectory(buildDir, &ec);
- if (db) {
- if (ec!=CXCompilationDatabase_NoError) {
- printf("unexpected error %d code while loading compilation database\n", ec);
- errorCode = -1;
- goto cdb_end;
- }
- for (i=0; i<argc && errorCode==0; ) {
- if (strcmp(argv[i],"lookup")==0){
- CCmds = clang_CompilationDatabase_getCompileCommands(db, argv[i+1]);
- if (!CCmds) {
- printf("file %s not found in compilation db\n", argv[i+1]);
- errorCode = -1;
- break;
- }
- numCmds = clang_CompileCommands_getSize(CCmds);
- if (numCmds==0) {
- fprintf(stderr, "should not get an empty compileCommand set for file"
- " '%s'\n", argv[i+1]);
- errorCode = -1;
- break;
- }
- for (j=0; j<numCmds; ++j) {
- CCmd = clang_CompileCommands_getCommand(CCmds, j);
- wd = clang_CompileCommand_getDirectory(CCmd);
- printf("workdir:'%s'", clang_getCString(wd));
- clang_disposeString(wd);
- printf(" cmdline:'");
- numArgs = clang_CompileCommand_getNumArgs(CCmd);
- for (a=0; a<numArgs; ++a) {
- if (a) printf(" ");
- arg = clang_CompileCommand_getArg(CCmd, a);
- printf("%s", clang_getCString(arg));
- clang_disposeString(arg);
- }
- printf("'\n");
- }
- clang_CompileCommands_dispose(CCmds);
- i += 2;
- }
- }
- clang_CompilationDatabase_dispose(db);
- } else {
- printf("database loading failed with error code %d.\n", ec);
- errorCode = -1;
- }
- cdb_end:
- free(tmp);
- return errorCode;
- }
- /******************************************************************************/
- /* USR printing. */
- /******************************************************************************/
- static int insufficient_usr(const char *kind, const char *usage) {
- fprintf(stderr, "USR for '%s' requires: %s\n", kind, usage);
- return 1;
- }
- static unsigned isUSR(const char *s) {
- return s[0] == 'c' && s[1] == ':';
- }
- static int not_usr(const char *s, const char *arg) {
- fprintf(stderr, "'%s' argument ('%s') is not a USR\n", s, arg);
- return 1;
- }
- static void print_usr(CXString usr) {
- const char *s = clang_getCString(usr);
- printf("%s\n", s);
- clang_disposeString(usr);
- }
- static void display_usrs() {
- fprintf(stderr, "-print-usrs options:\n"
- " ObjCCategory <class name> <category name>\n"
- " ObjCClass <class name>\n"
- " ObjCIvar <ivar name> <class USR>\n"
- " ObjCMethod <selector> [0=class method|1=instance method] "
- "<class USR>\n"
- " ObjCProperty <property name> <class USR>\n"
- " ObjCProtocol <protocol name>\n");
- }
- int print_usrs(const char **I, const char **E) {
- while (I != E) {
- const char *kind = *I;
- unsigned len = strlen(kind);
- switch (len) {
- case 8:
- if (memcmp(kind, "ObjCIvar", 8) == 0) {
- if (I + 2 >= E)
- return insufficient_usr(kind, "<ivar name> <class USR>");
- if (!isUSR(I[2]))
- return not_usr("<class USR>", I[2]);
- else {
- CXString x;
- x.data = (void*) I[2];
- x.private_flags = 0;
- print_usr(clang_constructUSR_ObjCIvar(I[1], x));
- }
- I += 3;
- continue;
- }
- break;
- case 9:
- if (memcmp(kind, "ObjCClass", 9) == 0) {
- if (I + 1 >= E)
- return insufficient_usr(kind, "<class name>");
- print_usr(clang_constructUSR_ObjCClass(I[1]));
- I += 2;
- continue;
- }
- break;
- case 10:
- if (memcmp(kind, "ObjCMethod", 10) == 0) {
- if (I + 3 >= E)
- return insufficient_usr(kind, "<method selector> "
- "[0=class method|1=instance method] <class USR>");
- if (!isUSR(I[3]))
- return not_usr("<class USR>", I[3]);
- else {
- CXString x;
- x.data = (void*) I[3];
- x.private_flags = 0;
- print_usr(clang_constructUSR_ObjCMethod(I[1], atoi(I[2]), x));
- }
- I += 4;
- continue;
- }
- break;
- case 12:
- if (memcmp(kind, "ObjCCategory", 12) == 0) {
- if (I + 2 >= E)
- return insufficient_usr(kind, "<class name> <category name>");
- print_usr(clang_constructUSR_ObjCCategory(I[1], I[2]));
- I += 3;
- continue;
- }
- if (memcmp(kind, "ObjCProtocol", 12) == 0) {
- if (I + 1 >= E)
- return insufficient_usr(kind, "<protocol name>");
- print_usr(clang_constructUSR_ObjCProtocol(I[1]));
- I += 2;
- continue;
- }
- if (memcmp(kind, "ObjCProperty", 12) == 0) {
- if (I + 2 >= E)
- return insufficient_usr(kind, "<property name> <class USR>");
- if (!isUSR(I[2]))
- return not_usr("<class USR>", I[2]);
- else {
- CXString x;
- x.data = (void*) I[2];
- x.private_flags = 0;
- print_usr(clang_constructUSR_ObjCProperty(I[1], x));
- }
- I += 3;
- continue;
- }
- break;
- default:
- break;
- }
- break;
- }
- if (I != E) {
- fprintf(stderr, "Invalid USR kind: %s\n", *I);
- display_usrs();
- return 1;
- }
- return 0;
- }
- int print_usrs_file(const char *file_name) {
- char line[2048];
- const char *args[128];
- unsigned numChars = 0;
- FILE *fp = fopen(file_name, "r");
- if (!fp) {
- fprintf(stderr, "error: cannot open '%s'\n", file_name);
- return 1;
- }
- /* This code is not really all that safe, but it works fine for testing. */
- while (!feof(fp)) {
- char c = fgetc(fp);
- if (c == '\n') {
- unsigned i = 0;
- const char *s = 0;
- if (numChars == 0)
- continue;
- line[numChars] = '\0';
- numChars = 0;
- if (line[0] == '/' && line[1] == '/')
- continue;
- s = strtok(line, " ");
- while (s) {
- args[i] = s;
- ++i;
- s = strtok(0, " ");
- }
- if (print_usrs(&args[0], &args[i]))
- return 1;
- }
- else
- line[numChars++] = c;
- }
- fclose(fp);
- return 0;
- }
- /******************************************************************************/
- /* Command line processing. */
- /******************************************************************************/
- int write_pch_file(const char *filename, int argc, const char *argv[]) {
- CXIndex Idx;
- CXTranslationUnit TU;
- struct CXUnsavedFile *unsaved_files = 0;
- int num_unsaved_files = 0;
- enum CXErrorCode Err;
- int result = 0;
-
- Idx = clang_createIndex(/* excludeDeclsFromPCH */1, /* displayDiagnostics=*/1);
-
- if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
- clang_disposeIndex(Idx);
- return -1;
- }
- Err = clang_parseTranslationUnit2(
- Idx, 0, argv + num_unsaved_files, argc - num_unsaved_files,
- unsaved_files, num_unsaved_files,
- CXTranslationUnit_Incomplete |
- CXTranslationUnit_DetailedPreprocessingRecord |
- CXTranslationUnit_ForSerialization,
- &TU);
- if (Err != CXError_Success) {
- fprintf(stderr, "Unable to load translation unit!\n");
- describeLibclangFailure(Err);
- free_remapped_files(unsaved_files, num_unsaved_files);
- clang_disposeTranslationUnit(TU);
- clang_disposeIndex(Idx);
- return 1;
- }
- switch (clang_saveTranslationUnit(TU, filename,
- clang_defaultSaveOptions(TU))) {
- case CXSaveError_None:
- break;
- case CXSaveError_TranslationErrors:
- fprintf(stderr, "Unable to write PCH file %s: translation errors\n",
- filename);
- result = 2;
- break;
- case CXSaveError_InvalidTU:
- fprintf(stderr, "Unable to write PCH file %s: invalid translation unit\n",
- filename);
- result = 3;
- break;
- case CXSaveError_Unknown:
- default:
- fprintf(stderr, "Unable to write PCH file %s: unknown error \n", filename);
- result = 1;
- break;
- }
-
- clang_disposeTranslationUnit(TU);
- free_remapped_files(unsaved_files, num_unsaved_files);
- clang_disposeIndex(Idx);
- return result;
- }
- /******************************************************************************/
- /* Serialized diagnostics. */
- /******************************************************************************/
- static const char *getDiagnosticCodeStr(enum CXLoadDiag_Error error) {
- switch (error) {
- case CXLoadDiag_CannotLoad: return "Cannot Load File";
- case CXLoadDiag_None: break;
- case CXLoadDiag_Unknown: return "Unknown";
- case CXLoadDiag_InvalidFile: return "Invalid File";
- }
- return "None";
- }
- static const char *getSeverityString(enum CXDiagnosticSeverity severity) {
- switch (severity) {
- case CXDiagnostic_Note: return "note";
- case CXDiagnostic_Error: return "error";
- case CXDiagnostic_Fatal: return "fatal";
- case CXDiagnostic_Ignored: return "ignored";
- case CXDiagnostic_Warning: return "warning";
- }
- return "unknown";
- }
- static void printIndent(unsigned indent) {
- if (indent == 0)
- return;
- fprintf(stderr, "+");
- --indent;
- while (indent > 0) {
- fprintf(stderr, "-");
- --indent;
- }
- }
- static void printLocation(CXSourceLocation L) {
- CXFile File;
- CXString FileName;
- unsigned line, column, offset;
-
- clang_getExpansionLocation(L, &File, &line, &column, &offset);
- FileName = clang_getFileName(File);
-
- fprintf(stderr, "%s:%d:%d", clang_getCString(FileName), line, column);
- clang_disposeString(FileName);
- }
- static void printRanges(CXDiagnostic D, unsigned indent) {
- unsigned i, n = clang_getDiagnosticNumRanges(D);
-
- for (i = 0; i < n; ++i) {
- CXSourceLocation Start, End;
- CXSourceRange SR = clang_getDiagnosticRange(D, i);
- Start = clang_getRangeStart(SR);
- End = clang_getRangeEnd(SR);
-
- printIndent(indent);
- fprintf(stderr, "Range: ");
- printLocation(Start);
- fprintf(stderr, " ");
- printLocation(End);
- fprintf(stderr, "\n");
- }
- }
- static void printFixIts(CXDiagnostic D, unsigned indent) {
- unsigned i, n = clang_getDiagnosticNumFixIts(D);
- fprintf(stderr, "Number FIXITs = %d\n", n);
- for (i = 0 ; i < n; ++i) {
- CXSourceRange ReplacementRange;
- CXString text;
- text = clang_getDiagnosticFixIt(D, i, &ReplacementRange);
-
- printIndent(indent);
- fprintf(stderr, "FIXIT: (");
- printLocation(clang_getRangeStart(ReplacementRange));
- fprintf(stderr, " - ");
- printLocation(clang_getRangeEnd(ReplacementRange));
- fprintf(stderr, "): \"%s\"\n", clang_getCString(text));
- clang_disposeString(text);
- }
- }
- static void printDiagnosticSet(CXDiagnosticSet Diags, unsigned indent) {
- unsigned i, n;
- if (!Diags)
- return;
-
- n = clang_getNumDiagnosticsInSet(Diags);
- for (i = 0; i < n; ++i) {
- CXSourceLocation DiagLoc;
- CXDiagnostic D;
- CXFile File;
- CXString FileName, DiagSpelling, DiagOption, DiagCat;
- unsigned line, column, offset;
- const char *DiagOptionStr = 0, *DiagCatStr = 0;
-
- D = clang_getDiagnosticInSet(Diags, i);
- DiagLoc = clang_getDiagnosticLocation(D);
- clang_getExpansionLocation(DiagLoc, &File, &line, &column, &offset);
- FileName = clang_getFileName(File);
- DiagSpelling = clang_getDiagnosticSpelling(D);
-
- printIndent(indent);
-
- fprintf(stderr, "%s:%d:%d: %s: %s",
- clang_getCString(FileName),
- line,
- column,
- getSeverityString(clang_getDiagnosticSeverity(D)),
- clang_getCString(DiagSpelling));
- DiagOption = clang_getDiagnosticOption(D, 0);
- DiagOptionStr = clang_getCString(DiagOption);
- if (DiagOptionStr) {
- fprintf(stderr, " [%s]", DiagOptionStr);
- }
-
- DiagCat = clang_getDiagnosticCategoryText(D);
- DiagCatStr = clang_getCString(DiagCat);
- if (DiagCatStr) {
- fprintf(stderr, " [%s]", DiagCatStr);
- }
-
- fprintf(stderr, "\n");
-
- printRanges(D, indent);
- printFixIts(D, indent);
-
- /* Print subdiagnostics. */
- printDiagnosticSet(clang_getChildDiagnostics(D), indent+2);
- clang_disposeString(FileName);
- clang_disposeString(DiagSpelling);
- clang_disposeString(DiagOption);
- clang_disposeString(DiagCat);
- }
- }
- static int read_diagnostics(const char *filename) {
- enum CXLoadDiag_Error error;
- CXString errorString;
- CXDiagnosticSet Diags = 0;
-
- Diags = clang_loadDiagnostics(filename, &error, &errorString);
- if (!Diags) {
- fprintf(stderr, "Trouble deserializing file (%s): %s\n",
- getDiagnosticCodeStr(error),
- clang_getCString(errorString));
- clang_disposeString(errorString);
- return 1;
- }
-
- printDiagnosticSet(Diags, 0);
- fprintf(stderr, "Number of diagnostics: %d\n",
- clang_getNumDiagnosticsInSet(Diags));
- clang_disposeDiagnosticSet(Diags);
- return 0;
- }
- static int perform_print_build_session_timestamp(void) {
- printf("%lld\n", clang_getBuildSessionTimestamp());
- return 0;
- }
- /******************************************************************************/
- /* Command line processing. */
- /******************************************************************************/
- static CXCursorVisitor GetVisitor(const char *s) {
- if (s[0] == '\0')
- return FilteredPrintingVisitor;
- if (strcmp(s, "-usrs") == 0)
- return USRVisitor;
- if (strncmp(s, "-memory-usage", 13) == 0)
- return GetVisitor(s + 13);
- return NULL;
- }
- static void print_usage(void) {
- fprintf(stderr,
- "usage: c-index-test -code-completion-at=<site> <compiler arguments>\n"
- " c-index-test -code-completion-timing=<site> <compiler arguments>\n"
- " c-index-test -cursor-at=<site> <compiler arguments>\n"
- " c-index-test -evaluate-cursor-at=<site> <compiler arguments>\n"
- " c-index-test -get-macro-info-cursor-at=<site> <compiler arguments>\n"
- " c-index-test -file-refs-at=<site> <compiler arguments>\n"
- " c-index-test -file-includes-in=<filename> <compiler arguments>\n");
- fprintf(stderr,
- " c-index-test -index-file [-check-prefix=<FileCheck prefix>] <compiler arguments>\n"
- " c-index-test -index-file-full [-check-prefix=<FileCheck prefix>] <compiler arguments>\n"
- " c-index-test -index-tu [-check-prefix=<FileCheck prefix>] <AST file>\n"
- " c-index-test -index-compile-db [-check-prefix=<FileCheck prefix>] <compilation database>\n"
- " c-index-test -test-file-scan <AST file> <source file> "
- "[FileCheck prefix]\n");
- fprintf(stderr,
- " c-index-test -test-load-tu <AST file> <symbol filter> "
- "[FileCheck prefix]\n"
- " c-index-test -test-load-tu-usrs <AST file> <symbol filter> "
- "[FileCheck prefix]\n"
- " c-index-test -test-load-source <symbol filter> {<args>}*\n");
- fprintf(stderr,
- " c-index-test -test-load-source-memory-usage "
- "<symbol filter> {<args>}*\n"
- " c-index-test -test-load-source-reparse <trials> <symbol filter> "
- " {<args>}*\n"
- " c-index-test -test-load-source-usrs <symbol filter> {<args>}*\n"
- " c-index-test -test-load-source-usrs-memory-usage "
- "<symbol filter> {<args>}*\n"
- " c-index-test -test-annotate-tokens=<range> {<args>}*\n"
- " c-index-test -test-inclusion-stack-source {<args>}*\n"
- " c-index-test -test-inclusion-stack-tu <AST file>\n");
- fprintf(stderr,
- " c-index-test -test-print-linkage-source {<args>}*\n"
- " c-index-test -test-print-visibility {<args>}*\n"
- " c-index-test -test-print-type {<args>}*\n"
- " c-index-test -test-print-type-size {<args>}*\n"
- " c-index-test -test-print-bitwidth {<args>}*\n"
- " c-index-test -test-print-type-declaration {<args>}*\n"
- " c-index-test -print-usr [<CursorKind> {<args>}]*\n"
- " c-index-test -print-usr-file <file>\n"
- " c-index-test -write-pch <file> <compiler arguments>\n");
- fprintf(stderr,
- " c-index-test -compilation-db [lookup <filename>] database\n");
- fprintf(stderr,
- " c-index-test -print-build-session-timestamp\n");
- fprintf(stderr,
- " c-index-test -read-diagnostics <file>\n\n");
- fprintf(stderr,
- " <symbol filter> values:\n%s",
- " all - load all symbols, including those from PCH\n"
- " local - load all symbols except those in PCH\n"
- " category - only load ObjC categories (non-PCH)\n"
- " interface - only load ObjC interfaces (non-PCH)\n"
- " protocol - only load ObjC protocols (non-PCH)\n"
- " function - only load functions (non-PCH)\n"
- " typedef - only load typdefs (non-PCH)\n"
- " scan-function - scan function bodies (non-PCH)\n\n");
- }
- /***/
- int cindextest_main(int argc, const char **argv) {
- clang_enableStackTraces();
- if (argc > 2 && strcmp(argv[1], "-read-diagnostics") == 0)
- return read_diagnostics(argv[2]);
- if (argc > 2 && strstr(argv[1], "-code-completion-at=") == argv[1])
- return perform_code_completion(argc, argv, 0);
- if (argc > 2 && strstr(argv[1], "-code-completion-timing=") == argv[1])
- return perform_code_completion(argc, argv, 1);
- if (argc > 2 && strstr(argv[1], "-cursor-at=") == argv[1])
- return inspect_cursor_at(argc, argv, "-cursor-at=", inspect_print_cursor);
- if (argc > 2 && strstr(argv[1], "-evaluate-cursor-at=") == argv[1])
- return inspect_cursor_at(argc, argv, "-evaluate-cursor-at=",
- inspect_evaluate_cursor);
- if (argc > 2 && strstr(argv[1], "-get-macro-info-cursor-at=") == argv[1])
- return inspect_cursor_at(argc, argv, "-get-macro-info-cursor-at=",
- inspect_macroinfo_cursor);
- if (argc > 2 && strstr(argv[1], "-file-refs-at=") == argv[1])
- return find_file_refs_at(argc, argv);
- if (argc > 2 && strstr(argv[1], "-file-includes-in=") == argv[1])
- return find_file_includes_in(argc, argv);
- if (argc > 2 && strcmp(argv[1], "-index-file") == 0)
- return index_file(argc - 2, argv + 2, /*full=*/0);
- if (argc > 2 && strcmp(argv[1], "-index-file-full") == 0)
- return index_file(argc - 2, argv + 2, /*full=*/1);
- if (argc > 2 && strcmp(argv[1], "-index-tu") == 0)
- return index_tu(argc - 2, argv + 2);
- if (argc > 2 && strcmp(argv[1], "-index-compile-db") == 0)
- return index_compile_db(argc - 2, argv + 2);
- else if (argc >= 4 && strncmp(argv[1], "-test-load-tu", 13) == 0) {
- CXCursorVisitor I = GetVisitor(argv[1] + 13);
- if (I)
- return perform_test_load_tu(argv[2], argv[3], argc >= 5 ? argv[4] : 0, I,
- NULL);
- }
- else if (argc >= 5 && strncmp(argv[1], "-test-load-source-reparse", 25) == 0){
- CXCursorVisitor I = GetVisitor(argv[1] + 25);
- if (I) {
- int trials = atoi(argv[2]);
- return perform_test_reparse_source(argc - 4, argv + 4, trials, argv[3], I,
- NULL);
- }
- }
- else if (argc >= 4 && strncmp(argv[1], "-test-load-source", 17) == 0) {
- CXCursorVisitor I = GetVisitor(argv[1] + 17);
-
- PostVisitTU postVisit = 0;
- if (strstr(argv[1], "-memory-usage"))
- postVisit = PrintMemoryUsage;
-
- if (I)
- return perform_test_load_source(argc - 3, argv + 3, argv[2], I,
- postVisit);
- }
- else if (argc >= 4 && strcmp(argv[1], "-test-file-scan") == 0)
- return perform_file_scan(argv[2], argv[3],
- argc >= 5 ? argv[4] : 0);
- else if (argc > 2 && strstr(argv[1], "-test-annotate-tokens=") == argv[1])
- return perform_token_annotation(argc, argv);
- else if (argc > 2 && strcmp(argv[1], "-test-inclusion-stack-source") == 0)
- return perform_test_load_source(argc - 2, argv + 2, "all", NULL,
- PrintInclusionStack);
- else if (argc > 2 && strcmp(argv[1], "-test-inclusion-stack-tu") == 0)
- return perform_test_load_tu(argv[2], "all", NULL, NULL,
- PrintInclusionStack);
- else if (argc > 2 && strcmp(argv[1], "-test-print-linkage-source") == 0)
- return perform_test_load_source(argc - 2, argv + 2, "all", PrintLinkage,
- NULL);
- else if (argc > 2 && strcmp(argv[1], "-test-print-visibility") == 0)
- return perform_test_load_source(argc - 2, argv + 2, "all", PrintVisibility,
- NULL);
- else if (argc > 2 && strcmp(argv[1], "-test-print-type") == 0)
- return perform_test_load_source(argc - 2, argv + 2, "all",
- PrintType, 0);
- else if (argc > 2 && strcmp(argv[1], "-test-print-type-size") == 0)
- return perform_test_load_source(argc - 2, argv + 2, "all",
- PrintTypeSize, 0);
- else if (argc > 2 && strcmp(argv[1], "-test-print-type-declaration") == 0)
- return perform_test_load_source(argc - 2, argv + 2, "all",
- PrintTypeDeclaration, 0);
- else if (argc > 2 && strcmp(argv[1], "-test-print-bitwidth") == 0)
- return perform_test_load_source(argc - 2, argv + 2, "all",
- PrintBitWidth, 0);
- else if (argc > 2 && strcmp(argv[1], "-test-print-mangle") == 0)
- return perform_test_load_tu(argv[2], "all", NULL, PrintMangledName, NULL);
- else if (argc > 2 && strcmp(argv[1], "-test-print-manglings") == 0)
- return perform_test_load_tu(argv[2], "all", NULL, PrintManglings, NULL);
- else if (argc > 1 && strcmp(argv[1], "-print-usr") == 0) {
- if (argc > 2)
- return print_usrs(argv + 2, argv + argc);
- else {
- display_usrs();
- return 1;
- }
- }
- else if (argc > 2 && strcmp(argv[1], "-print-usr-file") == 0)
- return print_usrs_file(argv[2]);
- else if (argc > 2 && strcmp(argv[1], "-write-pch") == 0)
- return write_pch_file(argv[2], argc - 3, argv + 3);
- else if (argc > 2 && strcmp(argv[1], "-compilation-db") == 0)
- return perform_test_compilation_db(argv[argc-1], argc - 3, argv + 2);
- else if (argc == 2 && strcmp(argv[1], "-print-build-session-timestamp") == 0)
- return perform_print_build_session_timestamp();
- print_usage();
- return 1;
- }
- /***/
- /* We intentionally run in a separate thread to ensure we at least minimal
- * testing of a multithreaded environment (for example, having a reduced stack
- * size). */
- typedef struct thread_info {
- int (*main_func)(int argc, const char **argv);
- int argc;
- const char **argv;
- int result;
- } thread_info;
- void thread_runner(void *client_data_v) {
- thread_info *client_data = client_data_v;
- client_data->result = client_data->main_func(client_data->argc,
- client_data->argv);
- }
- static void flush_atexit(void) {
- /* stdout, and surprisingly even stderr, are not always flushed on process
- * and thread exit, particularly when the system is under heavy load. */
- fflush(stdout);
- fflush(stderr);
- }
- int main(int argc, const char **argv) {
- thread_info client_data;
- atexit(flush_atexit);
- #ifdef CLANG_HAVE_LIBXML
- LIBXML_TEST_VERSION
- #endif
- client_data.main_func = cindextest_main;
- client_data.argc = argc;
- client_data.argv = argv;
- if (argc > 1 && strcmp(argv[1], "core") == 0) {
- client_data.main_func = indextest_core_main;
- --client_data.argc;
- ++client_data.argv;
- }
- if (getenv("CINDEXTEST_NOTHREADS"))
- return client_data.main_func(client_data.argc, client_data.argv);
- clang_executeOnThread(thread_runner, &client_data, 0);
- return client_data.result;
- }
|