2017-02-17 2 views
1

J'ai cette ligne dans un fichier d'en-tête:compilateur hexagonal ayant des problèmes avec `typedef struct mystruct * mystruct`

typedef struct mystruct *mystruct; 

Et la définition de struct correspondante dans un fichier .c. Pratiques assez standards.

Je reçois cette erreur de compilation:

fatal error: typedef redefinition with different types ('struct mystruct *' vs mystruct') 

est d'utiliser le compilateur Outils Hexagone (7.2.12) de SDK 3.0 Hexagone. C'est officiellement QuIC LLVM Hexagon Clang version 7.2.12. Bâtiment pour le vol de Snapdragon. Cela devrait fonctionner autant que je sache. Il fonctionne avec Ubuntu clang version 3.5.0-4ubuntu2 ~ trusty2 (basé sur LLVM 3.5.0) pour x86_64-pc-linux-gnu.

Quel est le problème ici? Ce type de typedef est-il une nouvelle fonctionnalité de C qui n'est pas implémentée dans le compilateur, ou plutôt les différences de compilation sont-elles communes?

Éditer: En fait, struct est défini dans un fichier .c, pas .cpp. Ajout de la sortie Makefile et make montrant la compilation avec Ubuntu clang, ainsi que le haut du fichier d'en-tête avec le problème typedef statment. Un test est exécuté à la fin, et tous les 105 tests passent.

Édition2: Voir la réponse de Jonathan Leffler pour les cas où cela fonctionne ou ne fonctionne pas.

ringbuf.h:

#include <stddef.h> 
#include <sys/types.h> 

#define MIN(a,b) (((a)<(b))?(a):(b)) 
#define MAX(a,b) (((a)>(b))?(a):(b)) 

typedef struct ringbuf_t *ringbuf_t; 

Makefile:

CC=clang 
CFLAGS=-O0 -g -Wall -Wpointer-arith -ftrapv -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error 

# or, for gcc... 
#CC=gcc 
#CFLAGS=-O0 -g -Wall 

LD=$(CC) 
LDFLAGS=-g 

test: ringbuf-test 
    ./ringbuf-test 

coverage: ringbuf-test-gcov 
     ./ringbuf-test-gcov 
     gcov -o ringbuf-gcov.o ringbuf.c 

valgrind: ringbuf-test 
     valgrind ./ringbuf-test 

help: 
    @echo "Targets:" 
    @echo 
    @echo "test - build and run ringbuf unit tests." 
    @echo "coverage - use gcov to check test coverage of ringbuf.c." 
    @echo "valgrind - use valgrind to check for memory leaks." 
    @echo "clean - remove all targets." 
    @echo "help - this message." 

ringbuf-test-gcov: ringbuf-test-gcov.o ringbuf-gcov.o 
    gcc -o ringbuf-test-gcov --coverage $^ 

ringbuf-test-gcov.o: ringbuf-test.c ringbuf.h 
    gcc -c $< -o [email protected] 

ringbuf-gcov.o: ringbuf.c ringbuf.h 
    gcc --coverage -c $< -o [email protected] 

ringbuf-test: ringbuf-test.o libringbuf.so 
    $(LD) -o ringbuf-test $(LDFLAGS) $^ -L$(MY_LIBS_PATH) -lringbuf 

ringbuf-test.o: ringbuf-test.c ringbuf.h 
    $(CC) $(CFLAGS) -c $< -o [email protected] 

libringbuf.so: ringbuf.o 
    $(CC) -shared -o libringbuf.so ringbuf.o 
    cp ./libringbuf.so $(MY_LIBS_PATH)/ 

ringbuf.o: ringbuf.c ringbuf.h 
    $(CC) $(CFLAGS) -fPIC -c $< -o [email protected] 
    cp ./ringbuf.h $(MY_INCLUDES_PATH)/ 

clean: 
    rm -f ringbuf-test ringbuf-test-gcov *.o *.so *.gcov *.gcda *.gcno 

.PHONY: clean 

make sortie:

clang -O0 -g -Wall -Wpointer-arith -ftrapv -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -c ringbuf-test.c -o ringbuf-test.o 
clang -O0 -g -Wall -Wpointer-arith -ftrapv -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -fPIC -c ringbuf.c -o ringbuf.o 
cp ./ringbuf.h /home/eric/Includes/ 
clang -shared -o libringbuf.so ringbuf.o 
cp ./libringbuf.so /home/eric/Libs/ 
clang -o ringbuf-test -g ringbuf-test.o libringbuf.so -L/home/eric/Libs -lringbuf 
./ringbuf-test 

Edit3: Cela fonctionne en fait très bien avec tout le compilateur Hexagone-clang. C'est le processus de compilation du plus grand programme que ce module existe dans ce qui est problématique. Je pense qu'il essaie de compiler ce code en C++.

+0

Vous réutilisez le nom 'mystruct'. Pourquoi voudriez-vous que cela fonctionne? –

+2

Ce code serait illégal en C++. Vous dites "un fichier .cpp" dans votre question. Mais vous avez étiqueté la question comme C. C et C++ sont des langues différentes. Veuillez décider quelle langue vous utilisez ... –

+2

De même, il n'est même pas courant en C d'utiliser le même nom pour une balise struct, et pour un pointeur vers ce type. Quand les gens utilisent des typedefs de pointeurs (ce qui est généralement déconseillé), ils ont tendance à utiliser une sorte de préfixe hongrois pour le typedef du pointeur (par exemple 'pmystruct'). –

Répondre

2

Votre code irait bien, en C et C++, si vous n'avez pas essayé de Use typedef for a pointer type.

L'en-tête (hdr.h par exemple) pourrait/devrait contenir:

typedef struct mystruct mystruct; 

La source (hdr.cpp par exemple) pourrait contenir:

#include "hdr.h" 

struct mystruct 
{ 
    const char *a; 
    int b; 
    int c; 
}; 

#include <iostream> 

int main() 
{ 
    mystruct *ap = new mystruct; 
    ap->a = "collywobbles"; 
    ap->b = 1; 
    ap->c = 2; 
    std::cout << "a: " << ap->a << ", b = " << ap->b << ", c = " << ap->c << "\n"; 
    return 0; 
} 

Cela compilera en C++, même dans les avertissements sévères . Un équivalent C main() utilisant <stdio.h> fonctionnerait en C.

+0

Pourquoi ce travail en .c mais pas .CPP – errolflynn

+1

Comme le montre le répondre, sans pointeur dans le 'typedef', le code fonctionne bien en C et C++. Si vous essayez d'inclure le pointeur dans le 'typedef', il ne fonctionnera pas en C++, mais (venu à penser) cela fonctionnerait, bien que confusément, en C, car la balise (struct, union, ENUM) espace de noms utilisé car 'struct mystruct' est séparé de l'espace de noms 'ordinary identifiers' utilisé pour les noms de typedef (et les noms de variables). –

+0

Il compile pour moi avec Ubuntu clang. J'ai posté le 'Makefile' et la sortie make. – errolflynn